@Catyee
2021-06-29T10:42:25.000000Z
字数 20658
阅读 1084
Spring
声明:下文中涉及的Spring源码都是Spring 5.3.7版本
Spring中用的最多的是单例bean,单例bean的创建、使用、销毁都是由Spring容器管理的,对于原型bean,spring只负责创建,在创建结束之后就不会再管了,销毁或释放资源都是要由开发者自己控制,所以我们经常说的"spring bean的生命周期"实际上指的是单例bean的生命周期。对于单例bean和原型bean以外类型的bean,由于使用的场景比较少,这里也不进行讲述。
Spring bean说到底也就是一个java对象,一个java对象的生命周期是什么样子的?首先通过构造器将对象实例化出来,如果构造器实例化的时候没有给属性赋值,在实例化之后还可以通过set方法给属性赋值,这之后就可以使用这个对象,使用完成之后被jvm回收掉。Spring bean也是java对象,所以和java对象一样spring bean的生命周期也离不开实例化 -> 使用 -> 最后销毁的过程,不过Spring作为一个功能全面、强大的框架,可以对bean的生命周期进行更细粒度的控制。除了实例化之外,还可以处理bean的依赖关系(依赖注入);可以对bean进行各种功能增强;也允许用户自定义一些初始化操作;对于单例bean来说,spring会将其保存在容器中,这样暂时使用完的bean不会被垃圾回收,下次使用的时候不需要再创建,而是直接获取。总之,Spring对bean的创建、使用、销毁进行了全面的接管,这也是IoC(控制反转)的具体体现。
详细来说我们可以把bean的生命周期分为如下几个阶段:
按照这样的划分我们来看Spring bean完整的生命周期:
BeanDefinitio即bean的建模器或者bean的定义器,它保存了一个Bean的所有信息,这些信息包括bean的属性、构造方法参数、显示依赖的Bean的名称(即@DependsOn注解中指定的bean名称)、是否单例、是否延迟加载、初始化和销毁方法等各种信息,Spring最终会根据BeanDefinition来创建对象。那BeanDefinition是什么时候创建的呢?
Spring容器在启动的时候会去扫描指定的包,识别出哪些类需要由spring接管,每扫描到一个类会生成一个MetadataReader对象,在这个对象中通过ASM框架(Java字节码操控框架,可以方便的解析出类中的所有元素:类名、方法、属性等,cglib动态代理底层也使用了ASM框架,其性能要远好于java反射)解析class文件,得到类的元数据信息和注解信息,通过这些信息就可以创建BeanDefinition对象了。这里要注意,扫描过程中获取的这些类本身没有进行类加载,所以这个时候jvm中还没有这些类的Class对象。
思考:
java中类的Class对象已经包含了类的各种信息,为什么还需要有一个专门的BeanDefinition来保存类的信息?
答案:
Class对象确实保存了一个类的所有信息,但是Spring实例化一个bean需要更多信息,比如是否懒加载,bean的scope,bean的依赖等等,这些是Class对象无法提供的,所以Spring专门设计了这样一个类来存储定义一个bean所需要的各种信息。
获取到bean的BeanDefinition之后就可以根据BeanDefinition创建bean了,Spring容器会按照字典序来创建非懒加载的这些Bean。
如果调试过这个创建的步骤,会发现Spring最终会调用到AbstractAutowireCapableBeanFactory类的createBean()方法,createBean()方法又会调用doCreateBean()方法,doCreateBean()还会调用initializeBean()方法,这三个方法执行结束,一个bean就真正意义的创建完成了,所以这三个方法非常重要,从这三个方法就可以了解创建bean和增强bean功能的整个过程。这里先贴出这三个方法的源码,省略了其中部分对理解生命周期不是特别重要的代码,比如异常处理之类的,然后对生命周期中重要的步骤进行了注释并标号,后面会对这些步骤详细讲解,可以对照来看。
AbstractAutowireCapableBeanFactory中第一个重要的方法——createBean:
// AbstractAutowireCapableBeanFactory中的createBean方法
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// 1、进行类加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
...
// 2、如果用户实现了InstantiationAwareBeanPostProcessor,则直接返回bean,并结束剩余创建流程(很少用到)
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
// 调用doCreateBean方法,这是上面提到的第二个重要的方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
AbstractAutowireCapableBeanFactory中第二个重要的方法——doCreateBean:
// AbstractAutowireCapableBeanFactory中的doCreateBean方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 3、推断构造器并实例化bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
if (!mbd.postProcessed) {
// 4、BeanDefinition的后置处理器,可以更改bean的属性等(很少用到)
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
...
Object exposedObject = bean;
// 5、处理依赖关系(依赖注入)
populateBean(beanName, mbd, instanceWrapper);
// 调用initializeBean方法,这是上面提到的第三个重要的方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
...
return exposedObject;
}
AbstractAutowireCapableBeanFactory中第三个重要的方法——initializeBean:
// AbstractAutowireCapableBeanFactory中的initializeBean方法
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// 6、执行aware接口(第一处扩展点)
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 7、执行bean后置处理器的前方法(第二处扩展点)
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 8、执行初始化方法(第三处扩展点)
invokeInitMethods(beanName, wrappedBean, mbd);
if (mbd == null || !mbd.isSynthetic()) {
// 9、执行bean后置处理器的后方法(第四处扩展点)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
上面标号的注释就是创建bean和增强bean的九个步骤,其中第二和第四步很少用到,剩余的七个都很重要,下面具体来看。
在前面有提到,扫描类的时候并没有进行类加载,但是实例化一个对象就必须要先进行类加载,所以AbstractAutowireCapableBeanFactory类的createBean()方法中做的第一件事就是进行类加载,对应上面源码中标号为1的注释的位置:
// 1、resolveBeanClass方法进行类加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
Spring允许不按照正常流程来创建一个Bean,开发者可以实现InstantiationAwareBeanPostProcessor接口,并在这个接口的postProcessBeforeInstantiation方法中返回一个Bean对象,如果这个对象不为空,就会结束剩余的创建流程,提前返回这个bean,这个bean如果是单例的话依然会放入到单例池中,只是不会进行依赖注入和功能增强。
// 2、提前返回bean,并结束生命周期
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
不过这种用法很少会用到,基本可以忽略这种用法。
实例化对象当然需要用到构造器,Spring可以推断构造器,选择合适的构造器来进行bean的实例化。
// 3、推断构造器并实例化bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
推断构造方法其实没那么复杂:
如果只有一个无参的构造方法,那么实例化就只能使用这个构造方法了。
如果有多个构造方法,其中一个是无参构造方法,其余的是有参构造方法,这些构造方法都没有@AutoWired注解,也没有在xml文件中进行设置,那么spring会默认选择无参构造方法。
如果有多个构造器,都是有参构造器,这些构造器上没有@AutoWired注解,也没有在xml文件中进行设置,spring启动时会报错。
如果只有一个有参构造器,这个构造器上没有@AutoWired注解,也没有在xml文件中进行设置,spring会看这个有参构造器的参数(可能是其它bean或者常量)是不是都能获取到,如果不能都获取到就会报错,如果都能获取到就会用这个构造器。
其它情况就看用户指定了哪个构造器,指定构造器有两种方式,一是通过@Autowired注解,二是通过xml中的<constructor-arg>标签来指定构造器参数,spring会根据参数来选择构造器,如果能找到一个合适的构造器,spring就会使用用户指定的构造器。但如果用户指定了多个构造器,比如在多个构造器上使用@Autowired注解或者通过xml标签不能推断出一个唯一的构造器,spring也会报错。
可能情况还不止上面这些,但是整体思路就是看spring能否找到一个不存在歧义的构造器(唯一的构造器或用户唯一指定的构造器),如果能找到,那么就使用这个构造器,如果找不到就看用户是否允许spring自动选择构造器,如果不允许就报错,如果允许就看spring自动选择的这个构造的参数是否都能获取到,如果都能获取到就会使用这个构造器,如果不能都获取到就会报错。
在BeanDefinition的后置处理中可以修改BeanDefinition,但是此时实例对象已经生成好了,所以想通过修改beanClass来改变bean对象已经没用了,但是这个时候bean只是实例化出来,还没进行依赖注入,所以可以修改PropertyValues:
if (!mbd.postProcessed) {
try {
// 4、BeanDefinition的后置处理器,可以更改bean的属性等
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
...
}
mbd.postProcessed = true;
}
这种用法也很少会用到,基本可以忽略。
populateBean()方法进行了属性填充,所谓属性填充其实就是依赖注入,spring会先去容器中寻找依赖的bean,如果找到了就直接注入,如果没有找到就会去创建依赖的bean,所以这个方法是一个递归的入口,等依赖的bean创建完之后,会接着进行当前bean的属性注入。这里就涉及到spring bean循环依赖的问题,这是一个比较复杂的问题,用一个单独的篇章来讲,详见:源码解析Spring循环依赖
// 5、处理依赖关系(依赖注入)
populateBean(beanName, mbd, instanceWrapper);
上面创建bean的步骤细分有很多步,但如果粗略划分,其实最重要的只有两步:一是实例化,二是属性填充,这两步也是创建一个java对象的过程。
在属性填充结束之后,从java的角度来说这个bean已经是一个完整的java对象,可以使用了。但是spring框架更进一步,通过各种扩展点来对bean的功能进行增强,这些扩展点都是用户可选的,并不是必须的。
第一处扩展点就是Aware接口,Aware单词有"发现.../对...有兴趣"的含义,从名字就可以看出来aware接口让用户能够从spring容器中获取一些有用的、感兴趣的信息或对象。Aware接口的执行对应上面源码中标号为6的注释的位置:
// 6、执行aware接口(第一处扩展点)
invokeAwareMethods(beanName, bean);
Aware接口有很多,这里列举几个常见的:
beanFactory和aplicationContext是spring容器不同程度上的抽象,BeanFactory接口定义了容器应该具有的基础行为,只要一个类实现了BeanFactory接口,我们就可以称它为容器。ApplicationContext接口组合了BeanFactory接口和一些其它接口,所以ApplicationContext接口扩展了容器的行为,我们称实现了BeanFactory接口的类为容器,那么实现了ApplicationContext接口的类也是容器,只是这个容器会具有更多的行为,使用起来会更加方便。
一个正在运行的spring应用只会有一个容器,但是jvm中可以同时有beanFactory和aplicationContext对象,这是不矛盾的,这种情况下beanFactory对象是aplicationContext对象的一个属性,相当于aplicationContext对象静态代理了beanFactory对象,这属于实现上的细节。正因为jvm中可以同时有beanFactory和aplicationContext对象,所以我们可以在一个bean上同时实现BeanFactoryAware和ApplicationContextAware接口,虽然这么做没有意义。
@Component
public class BeanC implements BeanFactoryAware, ApplicationContextAware {
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
BeanFactoryAware和ApplicationContextAware接口可以让我们获取到spring容器,这其实是实现依赖查找的关键,所谓依赖查找就是事先不进行bean的注入,而是在需要使用的时候从容器中查找,既然要从容器中查找,那必然要先获取容器对象,这两个接口可以让我们获取容器对象。
从通用的设计角度来说,一个框架可以允许用户在对象实例化完成之后执行一些操作,这些操作统一放在一个方法中,叫做初始化方法。Spring也一样,当spring将一个bean实例化完成之后,就会执行这个初始化方法。但是在这个初始化方法的前后还可以增加扩展点,做到全方位的可扩展,这就是bean后置处理器(BeanPostProcessor)的前方法和后方法,前方法就是初始化之前执行的方法,后方法是初始化之后执行的方法。
前方法的执行对应上面源码中标号为7的注释的位置:
// 7、执行bean后置处理器的前方法(第二处扩展点)
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
由于Bean后置处理器是比较重要的一块功能,涉及的内容也很多,所以用一个单独的章节讲解,详细内容请跳转到第六章。
这里面有一个特别要关注的点是@PostConstruct注解,这个注解用于标注一个方法,这个方法会在在bean实例化结束之后执行一些操作,和初始化方法的作用是一样的,但是我们知道@PostConstruct注解标注的方法会在初始化方法之前执行,这可以在Spring实现这个注解的方式中找到原因。细心的小伙伴会发现这个注解是javax包中的注解,并不是Spring自己的注解,Spring使用了CommonAnnotationBeanPostProcessor这个bean后置处理器来处理javax包中常用的注解,@PostConstruct注解就是其中之一,而且是在前方法中去执行这个注解标注的方法,这就是为什么@PostConstruct注解标注的方法会在初始化方法之前执行的原因,在第六章有源码解析,可以跳转查看。
与之相对的是@PreDestroy注解,这个注解也是javax包中的注解,也通过CommonAnnotationBeanPostProcessor的前方法来处理,但是和@PostConstruct不一样,@PostConstruct标注的方法会在前方法中直接执行,而@PreDestroy不会直接执行,而是暂时保存起来等到bean销毁之前执行。
Spring允许用户自定义一些操作,这些操作会在bean实例化完成之后执行,这些操作放在一个统一的方法中叫做初始化方法。
初始化方法有多种指定方式,这里列举最为常用的两种,第一种是实现InitializingBean接口,在这个接口的afterPropertiesSet()方法中定义初始化操作;第二种是在xml配置文件中通过init-method标签指定初始化方法,现在用xml配置文件的方式已经比较少了。这两种方式可以共存,会先执行在afterPropertiesSet()方法,然后执行init-method标签指定初始化方法,但是一般不会有人同时混用这两种方式。
初始化方法的执行对应上面源码中标号为8的注释的位置:
// 8、执行初始化方法(第三处扩展点)
invokeInitMethods(beanName, wrappedBean, mbd);
初始化方法之后的扩展点就是bean后置处理器的后方法,这里典型的应用就是Spring AOP的功能实现,Spring AOP底层用的是动态代理,代理对象就是在Bean后置处理器的后方法中进行生成的,详细内容请跳转到第六章。
后方法的执行对应于上面源码中标号为9的注释的位置:
// 9、执行bean后置处理器的后方法(第四处扩展点)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
这一步执行完之后一个bean就真正意义的创建完成,如果是单例bean还会加入到单例池中,之后就可以真正使用了,直到最后在容器关闭的时候被销毁。
容器销毁的时候会进行单例bean的销毁。可以想象一下,如果所有单例bean都没有定义销毁方法,那么容器只需要直接清空保存单例bean的缓存就可以了。但如果有一些单例bean定义了销毁方法,就需要找出这些单例bean,执行销毁方法,执行完之后再清空单例bean的缓存。所以先要找出那些定义了销毁方法的bean,然后执行这些销毁方法。有多种方式来定义销毁方法,这里列举最为常用的三种方式
Spring使用了适配器模式来统一这些销毁方法的处理方式,这个适配器就是DisposableBeanAdapter,最终会在这个适配器中的destroy方法中来执行具体的销毁方法。
// DisposableBeanAdapter中的destroy方法
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
// 执行@PreDestroy注解标注的方法
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
// 执行DisposableBean接口的destroy()方法
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
...
}
}
// 执行xml标签中指定的销毁方法或者其他方式指定的销毁方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
} else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
上面提到的三种销毁方法可以同时存在,先执行@PreDestroy标注的方法,然后执行DisposableBean接口的destroy()方法,最后执行xml中destry-method标签指定的销毁方法。当然没有必要同时混用这几中方法。
Spring Bean是java对象的一种特例,所以和java对象一样需要实例化和填充属性,但是Spring作为框架还可以在bean实例化并填充属性之后进行各种功能增强。实例化、填充属性、增强功能这是Spring Bean生命周期最为主要的三个阶段,如果简略划分甚至可以把这三个阶段作为Spring Bean的生命周期。当然如果进一步细分就是如下五个阶段:
最后来看一看Spring Bean生命周期中有一些成对的接口或者注解,比如:
这些成对的接口或注解用于定义一些初始化操作和销毁操作,在使用上都是类似的,执行顺序上也是类似的,初始化时先执行@PostConstruct注解标注的方法,然后是afterPropertiesSet()方法,然后是init-method指定的方法;销毁时先执行@PreDestroy注解标注的方法,然后是destroy()方法,然后是destroy-method标签指定的方法。
Spring允许一个bean实例化完成之后执行一些操作,这些操作统一放在一个方法中,叫做初始化方法,在这个初始化方法的前后还可以增加功能扩展点,这两个扩展点就是通过bean的后置处理器(BeanPostProcesser接口)来完成的,在初始化方法之前的扩展点对应的是BeanPostProcesser的postProcessBeforeInitialization()方法,为了便于描述可以简单称为bean后置处理器的前方法;初始化方法之后的扩展点对应的是BeanPostProcesser的postProcessAfterInitialization()方法,称为bean后置处理器的后方法。之所以叫做bean的后置处理器,是因为它是在bean实例化完成之后执行的。
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//bean初始化方法调用后被调用
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
可以看到BeanPostProcesser是一个接口,开发者可以自己实现BeanPostProcesser接口来对bean进行某种功能的增强。但是BeanPostProcesser接口和Aware接口不一样,Aware接口是bean直接继承的,影响的只有实现接口的这一个bean,而BeanPostProcesser接口是需要单独实现的,影响的是所有的用户bean,Spring启动的时候会先注册所有的bean后置处理器,然后创建bean,所以一旦一个BeanPostProcesser注册成功就会在所有bean的创建过程中执行。
比如按如下代码自定义一个Bean后置处理器:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + ": Exec before init");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + ": Exec after init");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
那么所有的bean在创建过程中都会打印日志。
BeanPostProcesser是一个接口,我们可以自己实现这个接口,用于在bean初始化方法之前和之后进行功能增强。另一方面,Spring本身也运用这个接口来实现一些功能。典型的例子就是CommonAnnotationBeanPostProcessor和AnnotationAwareAspectJAutoProxyCreator,这两个类都实现了BeanPostProcessor接口,所以都是Bean后置处理器,但是要注意这两个类还实现了其它接口,功能是复杂的,并不是单纯的Bean后置处理器。
CommonAnnotationBeanPostProcessor这个类用来处理javax包中扩展的注解,这些注解包括@Resource、@WebServiceRef、@EJB、@PostConstruct、@PreDestroy,这五个注解中最为常用的是@Resource、@PostConstruct、@PreDestroy,但是这5个注解中只有@PostConstruct和@PreDestroy这两个注解用到了Bean后置处理器接口,看源码:
// CommonAnnotationBeanPostProcessor继承了InitDestroyAnnotationBeanPostProcessor,InitDestroyAnnotationBeanPostProcessor中有前方法和后方法的具体实现:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在bean的class中寻找是否有@PostConstruct和@PreDestroy这两个注解,构造LifecycleMetadata对象
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 如果有@PostConstruct注解,将直接执行这个注解标注的方法
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
...
} catch (Throwable ex) {
...
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
可以看到CommonAnnotationBeanPostProcessor的前方法中扫描了bean的Class对象,看其中是否有@PostConstruct和@PreDestroy这两个注解,然后构造出LifecycleMetadata对象。如果有@PostConstruct注解,这个注解标注的方法还会在前方法中立刻执行,@PreDestroy则是在bean销毁之前执行。
其它的三个注解则没有通过Bean后置处理器的前后方法进行处理,之前说过CommonAnnotationBeanPostProcessor是复杂的,不仅实现了BeanPostProcessor接口,也实现了其它接口,这几个注解是通过其它接口定义的方法实现的,有兴趣可以去看源码,这里聚焦于Bean后置处理器的功能,所以不进行展开。
我们知道@Resource注解和@Autowired注解对应,都用于进行依赖注入,@Resource通过CommonAnnotationBeanPostProcessor来实现,@Autowired则是通过AutowiredAnnotationBeanPostProcessor来实现的,这个类用来处理@AutoWired、@Values、 java.inject.Inject这三个注解,AutowiredAnnotationBeanPostProcessor同样继承了BeanPostProcessor这个接口,所以也是bean后置处理器,但是看源码就会发现这个Bean后置处理器的前、后方法都是空方法,所以这些注解的功能都是通过其它接口定义的方法来实现的,之所以要把这个类定义为Bean的后置处理器只是为了统一处理:Spring在启动的时候会先扫描所有的Bean后置处理器并注册,这个过程中会把AutowiredAnnotationBeanPostProcessor给注册进去。
@Resource注解和@Autowired注解不使用bean后置处理器来实现的原因也很容易理解,这两个注解是用来进行依赖注入的,spring创建bean的时候是先处理依赖注入(populateBean方法),然后才会执行bean后置处理器的前后方法(initializeBean方法),如果这两个注解使用bean后置处理器来实现和创建bean的流程矛盾了。
AnnotationAwareAspectJAutoProxyCreator用于实现Spring的AOP功能。我们知道Spring的AOP底层用的是动态代理技术,这意味着在Spring容器中最终保存的应该是增强过后的代理对象,而不是原始的对象,那Spring是怎么做到这一点的呢?其实就是用到了BeanPostProcesser接口,在BeanPostProcesser接口的后方法中判断当前bean是否需要植入切面逻辑,如果需要就生成一个代理对象。这个实现了BeanPostProcesser接口的类是AnnotationAwareAspectJAutoProxyCreator,看源码:
// AnnotationAwareAspectJAutoProxyCreator继承自AbstractAutoProxyCreator,在这个类中有后方法的实现
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 有关循环依赖
// 如果检测到aop的设置,则创建代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
这里还牵扯到循环依赖相关的事项,这里不进行展开,有单独的篇章讲解,见:源码解析Spring循环依赖
从上面的讲解可以看到Spring框架本身已经有了很多bean后置处理器,开发者自己也可以定义很多bean后置处理器,那这些bean后置处理器的执行顺序是什么样的呢?我们来看注册Bean后置处理器的实现逻辑,其实原本的注释已经解释的很详细了:
// 注册方法在PostProcessorRegistrationDelegate这个工具类中
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 处理bean后置处理器的主要思路是将bean后置处理器进行分离,将实现了PriorityOrdered接口、Ordered接口的bean后置处理器和剩余的进行分离,分别排序之后再分别向spring容器注册
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先注册实现了PriorityOrdered接口的bean后置处理器,这包括AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 然后注册实现了Ordered接口的bean后置处理器,这包括AnnotationAwareAspectJAutoProxyCreator
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 然后注册剩余的bean后置处理器,包括用户自定义的普通bean后置处理器(没有实现PriorityOrdered接口和Ordered接口),这些后置处理器按加载的顺序放入到list中,加载是按照字典序加载的,所以这里的顺序也是字典序
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 最后重新注册internalPostProcessors中的bean后置处理器,也就是那些实现了MergedBeanDefinitionPostProcessor接口的bean后置处理器,包括AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,重新注册会将这些bean后置处理器从列表的前面移除,然后放到列表的最后。
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
上面代码关键步骤我添加了中文注释,处理bean后置处理器的主要思路是将bean后置处理器进行分离,将实现了PriorityOrdered接口、Ordered接口的Bean后置处理器和剩余的进行分离,分别排序之后再分别向spring容器注册,所谓注册就是将这些Bean后置处理器放入到容器中的一个List中去,这里要注意都是是先排序再注册,放入到容器中的list之后不会再进行排序,也就是说先注册的必然在list的前面。
AnnotationAwareAspectJAutoProxyCreator的order是Ordered.LOWEST_PRECEDENCE(值为2147483647),是最低的优先级;CommonAnnotationBeanPostProcessor也是这个值,也是最低的优先级;AutowiredAnnotationBeanPostProcessor是Ordered.LOWEST_PRECEDENCE - 2,比CommonAnnotationBeanPostProcessor略高一点;用户自定义的bean后置处理器一般不会实现PriorityOrdered接口和Ordered接口,则是按照加载的顺序排序,也就是字典序。按照源码执行的流程,容器中bean后置处理器最终的顺序是: