注解的收集与依赖注入、initializeBean、Bean的销毁
一、收集注解
实例化Bean只是在堆内存划了一片空间,Bean中带有@Autowired注解的属性是没有值的。在上一篇提到的doCreateBean里,applyMergedBeanDefinitionPostProcessors中MergedBeanDefinitionPostProcessor的实现类会收集各种注解,有CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor、等。
CommonAnnotationBeanPostProcessor支持@PostConstruct,@PreDestroy,@Resource注解的收集。
AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解的收集。
举例说明@Autowired注解的收集,其他的注解收集与之类似。在AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition的findAutowiringMetadata
中metadata = buildAutowiringMetadata(clazz);
收集带有@Autowired的字段和方法。先收集到容器里,再把容器和Class封装成InjectionMetadata,放到缓存injectionMetadataCache中后返回。
二、依赖注入
populateBean中支持了@Autowired依赖注入过程。首先看实现了InstantiationAwareBeanPostProcessor接口的调用,在postProcessAfterInstantiation方法中返回false可以让所有类都不能依赖注入。当然,也可以在方法中写逻辑判断,实现部分类依赖注入。
接着从这里可以看到依赖注入过程。
来到AutowiredAnnotationBeanPostProcessor.postProcessProperties,首先从缓存中拿到InjectionMetadata对象(InjectionMetadata是在applyMergedBeanDefinitionPostProcessors中加入到缓存的)。
AutowiredAnnotationBeanPostProcessor.inject的beanFactory.resolveDependency
会触发依赖注入属性的getBean操作,这个里面涉及到各种类型的判断,不用深入的去看。
最后,通过反射完成属性和方法的依赖注入。
三、initializeBean
doCreateBean的initializeBean是实例化和依赖注入完以后的调用。
1. 调用Aware接口
在invokeAwareMethods中可以看到,这个里面是各种Aware接口的调用。比如说,BeanNameAware.setBeanName可以拿到beanName,BeanFactoryAware.setBeanFactory可以拿到beanFactory对象。
2. 对类中某些特殊方法的调用,比如@PostConstruct,Aware接口
来到applyBeanPostProcessorsBeforeInitialization,这里循环调用BeanPostProcessor的postProcessBeforeInitialization方法。下面举一些例子。
在InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization中看到,可以从缓存中取出带有@PostConstruct的方法,反射调用方法。
在ApplicationContextAwareProcessor.postProcessBeforeInitialization中是对EnvironmentAware、ApplicationEventPublisherAware等Aware接口的支撑。
在ImportAwareBeanPostProcessor.postProcessBeforeInitialization中可以看到,在ImportAware的实现类的setImportMetadata方法中调用AnnotationMetadata.getAnnotations()能拿到import了这个Bean的类的注解。
例如,ImportBean通过@import注解import了AwareBean,如果AwareBean实现了ImportAware接口,就可以在setImportMetadata方法中通过AnnotationMetadata.getAnnotations()拿到ImportBean的所有注解。
3. InitializingBean接口、init-method属性调用
接着来到invokeInitMethods,这里调用了实现InitializingBean接口的afterPropertiesSet方法。
下面是对xml中init-method方法的调用。获取init-method属性中的方法,判断方法名称不为afterPropertiesSet,最后反射调用方法。
从这里可以看到,带有@PostConstruct的方法、实现InitializingBean接口的afterPropertiesSet方法、init-method配置的方法,这3类方法的作用都是一样的,都是在Bean实例化完成后做一些操作。区别是调用的时序不一样,带有@PostConstruct的方法最开始执行,然后是InitializingBean接口的afterPropertiesSet方法,最后是init-method配置的方法。
4. 另外一些BeanPostProcessor的调用
从applyBeanPostProcessorsAfterInitialization进入,和applyBeanPostProcessorsBeforeInitialization一样,这里也是循环BeanPostProcessor,调用postProcessAfterInitialization方法。例如,会