反射——依赖注入框架原理
抽象工厂方法,FactoryBean.getBean(“”) –> Class.forName(“”). newInstance()
forName()是静态方法
单例Singleton(饱汉、饿汉)
- 创建对象
this.class.getClassLoader.loadClass(""). newInstance();
此处写XML配置,利用properties对象读入inputStream,读取配置作为className
三个类: Class/Field/Method
clazz.getMethod() getField(); field.get(Object obj) method.invoke(Object obj, Object… args) - 类装载器,父类加载,委托
graph TD
A[BootStrap ClassLoader] -->B(ExtClassLoader)
B[ExtClassLoader] -->C(AppClassLoader)
C[AppClassLoader] -->D(Custom Loader)
动态代理
动态代理是基于什么原理
反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect,官方用语)的能力。通过反射我们可以直接操作类或者对象,比如获取某个对象的类定义,获取类声明的属性和方法,调用方法或者构造对象,甚至可以运行时修改类定义。
动态代理是一种方便运行时动态构建代理、动态处理代理方法调用的机制,很多场景都是利用类似机制做到的,比如用来包装 RPC 调用、面向切面的编程(AOP)。
实现动态代理的方式很多,比如 JDK 自身提供的动态代理,就是主要利用了上面提到的反射机制。还有其他的实现方式,比如利用传说中更高性能的字节码操作机制,类似 ASM、cglib(基于 ASM)、Javassist 等。
@w=300
在静态代理基础上,静态代理没有引入Proxy类,需手动编码把被代理类作为属性引入
java代理,代理有2种,一种是jdk,代理与目标实现同一个接口,一种是CGLIB代理继承目标类
我们先关注jdk动态代理:
- 创建一个有相同接口的代理类Proxy—-JDK自动生成字节码。该代理类有一个属性invocationHandler,并有带该入参的构造方法
Class proxy = Proxy.getProxyClass( Foo.class.getClassLoader(), new Class[] { Foo.class } );
- 创建新类 invocationHandler,实现invocationHander接口的invoke(Proxy, method, args)方法实现
InvocationHandler invocationHandler = new MyInvocationHandler implements InvocationHandler( public Object invoke() );
//实现 invoke()方法
- 实例化一个Proxy,参数是invocationHandler
//取带参数的构造方法,创建对象时传入参数
proxy.getConstructor( new Class[]{ InvocationHandler.class } ).newInstance( invocationHandler );
优化二: 2和3合成一步,匿名内部类
优化三:1、2、3合成一步
Proxy.newInstance( ClassLoader, new Class[]{ InvocationHandler.class }, new InvocationHandler({ public Object invoke( Object proxy, Method method, Object[] args ){} }))
spring的aop基础源码(面向切面编程)
框架原理:动态代理 target–advice 日志、安全、事务
Class.for("proxyFactoryBean").newInstance()
proxyFactoryBean.setAdvice(advice);
proxyFactoryBean.setTarget(target);
- proxyFactoryBean.getProxy()
有2个成员属性advice,target,这2个属性可在xml里配置,也是反射,通过构造方法注入。getProxy()方法里包含动态代理的代码, - proxy的invoke方法已经加进了
advice.beforMethod();
method.invoke(target, args);
advice.afterMethod();
- 我们的任务是写
MyAdvice implements Advice{
public beforeMethod(){
//doSomething();
}
public afterMethod(){
//doSomething();
}
}
枚举
枚举是抽象abstract类,有一个默认属性name,每个值(public)是类的一个实例对象.
枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象
构造方法是私有的,
枚举类中可包含方法: 1.实现普通的next方法
2.实现抽象的next方法: 每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义。
泛型
jdk1.5引入泛型
泛型提供给javac编译器使用,限定集合中的输入类型,在编译后会擦除。
除了集合使用泛型,反射中Class,Constructor也使用泛型,标记属于什么类,减少类型转换的操作
通配符<? extends Object> 上边界 下边界
1.泛型集合
Collection collection = new ArrayList();
2.泛型方法: 由C++的模板函数引出,T代表任意类型。
2.1
2.2 调用者,建议大家看看传智播客的巴巴运动网视频中的BaseDao的代码。无需对返回值进行类型转换
3.泛型类
内部类
主要有以下几类:成员内部类(在方法体里创建 有访问说明符)、局部内部类(在方法体里创建,不能有访问说明符)、静态内部类()、匿名内部类(没有类名)
为什么需要内部类?
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
内部类主要有以下几类:成员内部类、局部内部类、静态内部类、匿名内部类
super(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(BmapRgeoCommand.class.getSimpleName())), config, client, query);
Java异常与错误
- Exception
- checked 编译器检查
- IOException
- unchecked 运行时异常
- NullPointerException
- ArrayIndexOutOfBoundsException
- ClassNotFoundException
- RuntimeException
- Error
- OutOfMemoryError 内存溢出错
- NoClassDefFoundError
Java的checked exception总是被诟病,可我是从C#转到Java开发上来的,中间经历了go,体验过scala。我觉得Java这种机制并没有什么不好,不同的语言体验下来,错误与异常机制真是各有各的好处和槽点,而Java我觉得处在中间,不极端。当然老师提到lambda这确实是个问题…至于响应式编程,我可以泛化为异步编程的概念嘛?一般各种异步编程框架都会对异常的传递和堆栈信息做处理吧?比如promise/future风格的。本质上大致就是把lambda中的异常捕获并封装,再进一步延续异步上下文,或者转同步处理时拿到原始的错误和堆栈信息
谈谈 final、finally、 finalize 有什么不同?
final修饰类,变量,方法,表示不可继承,修改,重载
finally是异常捕捉后执行的语句
finalize是GC内存回收
【final关键字的具体应用】:
【final+变量】: 不能被修改 在实际应用中,这种形式是非常少见的。 比如logger是可以的,但是貌似并不是非常实用,或许用户仍然希望通过setter来改变logger变量。
【static+final+变量】: 1、编译期常量,永远不可改变。2、运行期初始化时,我们希望它不会被改变。常量。经常使用
【final+方法】: 不能被重写,仍然可以继承这个方法,也就是说可以直接使用。JDK中常用,但是开发者并未常用。
【final+类】: 不能被继承, helper类经常使用。
【final用于匿名内部类的参数传递】:
在多线程测试时,经常使用。{内部类不能访问局部变量,局部变量需加final }
【final用于方法的参数】: 并不常用。
对比Hashtable、HashMap、TreeMap有什么不同?
HashMap 的设计和实现细节,相应的源码解读,
hashMap的,数组加链表,桶,负载因子与容量,哈希碰撞
并发,无限循环,消耗cpu
HashMap 的性能表现非常依赖于哈希码的有效性,请务必掌握 hashCode 和 equals 的一些基本约定
谈谈接口和抽象类有什么区别?
abstract
interface
定义出语法基本正确的接口、抽象类或者相关继承实现,涉及重载(Overload)、重写(Override)
我们一定要清楚面向对象的基本要素:封装、继承、多态。
- Single Responsibility
- Open-Close
- Liskov Substitution
- Interface Segregation
- Dependency Injection
S.O.L.I.D 原则。单一职责(Single Responsibility),类或者对象最好是只有单一职责,在程序设计中如果发现某个类承担着多种义务,可以考虑进行拆分。
开关原则(Open-Close, Open for extension, close for modification),设计要对扩展开放,对修改关闭。换句话说,程序设计应保证平滑的扩展性,尽量避免因为新增同类功能而修改已有实现,这样可以少产出些回归(regression)问题。
里氏替换(Liskov Substitution),这是面向对象的基本要素之一,进行继承关系抽象时,凡是可以用父类或者基类的地方,都可以用子类替换。
接口分离(Interface Segregation),我们在进行类和接口设计时,如果在一个接口里定义了太多方法,其子类很可能面临两难,就是只有部分方法对它是有意义的,这就破坏了程序的内聚性。对于这种情况,可以通过拆分成功能单一的多个接口,将行为进行解耦。在未来维护中,如果某个接口设计有变,不会对使用其他接口的子类构成影响。
依赖反转(Dependency Inversion),实体应该依赖于抽象而不是实现。也就是说高层次模块,不应该依赖于低层次模块,而是应该基于抽象。实践这一原则是保证产品代码之间适当耦合度的法宝。
数据库事务
- 原子性 所有操作要么全成功,要么回滚全失败
- 一致性 数据库的多表数据的完整性和一致性
- 隔离性 并发过程,各线程相互隔离互不影响
> 并发问题:脏读;幻读;不可重复读
- 隔离级别:读未提交
- 读已提交
- 可重复读
- 串行化
- 持久性 数据的改变就是永久性,不会丢失
访问符号
访问权限 | 类 | 包 | 子类 | 其他包 |
---|---|---|---|---|
public | ∨ | ∨ | ∨ | ∨ |
protect | ∨ | ∨ | ∨ | × |
default | ∨ | ∨ | × | × |
private | ∨ | × | × | × |
Http协议与Tcp/IP协议
TCP 建连与断连:TCP 的滑动窗口时,能讲到流量和拥塞控制:三次握手
Leave a Reply