BeanFactory
BeanFactory 是一个接口,提供了获取容器中Bean的相关方法。
BeanDefinitionRegistry 它才是IoC的容器,用于存储、管理所有的Bean对象。
DefaultListableBeanFactory 它是IoC容器的一个具体实现,实现了BeanFactory和BeanDefinitionRegistry接口,因此既拥有管理Bean的容器,又拥有访问Bean的方法。
BeanDefinition 每一个Bean都有一个BeanDefinition与之对应,用于存储Bean的相关信息:对象的class类型、是否是抽象类、构造方法参数等。RootBeanDefinition和ChildBeanDefinition是BeanDefinition的两个主要的实现类。
BeanDefinitionReader 在Spring中,标注Bean的依赖关系有四中方式:直接在代码setter、构造器中声明;通过XML文件声明;通过Properties文件声明;通过注解声明。BeanDefinitionReader接口的作用就是读取配置文件中的bean信息,把它们解析成BeanDefinition对象,然后注册到BeanDefinitionRegistry中去。PropertiesBeanDefinitionReader和XmlBeanDefinitionReader是该接口的两个实现类,分别用于解析properties和xml格式的配置文件。
初始化阶段
- 容器启动阶段 该阶段Spring会使用BeanDefinitionReader加载配置文件,并把所有的bean解析成BeanDefinition对象,并注册到BeanDefinitionRegistry。
- Bean实例化阶段 惰性加载,对于BeanFactory容器,当调用者主动调用getBean方法或者因存在依赖关系容器隐式调用getBean时,如果当前Bean尚未初始化,或者bean配置成prototype,就会触发Bean实例的初始化。
代理
可以实现业务逻辑和额外逻辑的解耦,在不修改委托类代码的情况下能够做一些额外的处理。
静态代理
若代理类在程序运行前就已经存在,那么这种代理方式称为静态代理,这种情况下的代理类通常都是我们在Java代码中定义的。静态代理可以通过聚合来实现,让代理类持有一个委托类的引用即可。继承同一个类或者接口,实现同样的方法,代理类加上自己额外的操作,再调用目标类的同样的方法。可以产生代理对象的静态代理工厂类,封装两个类。
动态代理
代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
通过静态代理实现我们的需求需要我们在每个方法中都添加相应的逻辑,这里只存在两个方法所以工作量还不算大,假如包含上百个方法呢?这时候使用静态代理就会编写许多冗余代码。
在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口、另一个则是 Proxy类,这个类和接口是实现我们动态代理所必须用到的。
public class DynamicProxy implements InvocationHandler {
private Object obj; //obj为委托类对象;
public DynamicProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(obj, args);
System.out.println("after");
return result;
}
}
public class ProxyFactory {
...
public static Object getDynProxy(Object target) {
InvocationHandler handler = new DynProxyLawyer(target);
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
}
}
首先Jdk的动态代理实现方法是依赖于接口的,首先使用接口来定义好操作的规范。然后通过Proxy类产生的代理对象调用被代理对象的操作,而这个操作又被分发给InvocationHandler接口的 invoke方法具体执行
CGLIB
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
JDK代理要求被代理的类必须实现接口,有很强的局限性。而CGLIB动态代理则没有此类强制性要求。简单的说,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。