最近把@Autowired注解的解析过程粗略的跟读了一下,记录一下解析流程。
BeanPostProcessor接口是Spring的Bean后置处理核心接口,在Bean初始化前后进行一些处理工作。很多解析器都实现了该接口,该接口有两个重要方法,即Bean初始化之前的postProcessBeforeInitialization和Bean初始化之后的postProcessAfterInitialization。
public interface BeanPostProcessor
{
Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException;
Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException;
}
BeanPostProcessor的实现类:
1、定位注解解析器
既然BeanPostProcessor有那么多实现类,那具体是哪个处理器在解析@Autowired注解呢?写了一个单元测试类,自动注入一个car属性,故意没有通过任何方式初始化car的bean,所以解析器执行到自动注入@Autowired标记的属性时报错了,如下:
这样就能定位到是AutowiredAnnotationBeanPostProcessor在解析@Autowired标签:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.bill99.bean.Car com.bill99.route.service.MyAutowiredTest.car; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.bill99.bean.Car] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:531)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:295)
... 26 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.bill99.bean.Car] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:997)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:867)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:779)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:503)
2、解读注解解析器
这个序列图是通过调用栈梳理出来的,作为参考,下面对每一步进行解读:
从测试方法入口SpringJUnit4ClassRunner开始,调用栈先调用AbstractApplicationContext.refresh()//读取配置刷新容器,源码如下:
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh();? // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();? // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory);? try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory);? // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory);? // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory);? // Initialize message source for this context. initMessageSource();? // Initialize event multicaster for this context. initApplicationEventMulticaster();? // Initialize other special beans in specific context subclasses. onRefresh();? // Check for listener beans and register them. registerListeners();? // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory);? // Last step: publish corresponding event. finishRefresh(); }? catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); }? // Destroy already created singletons to avoid dangling resources. destroyBeans();? // Reset 'active' flag. cancelRefresh(ex);? // Propagate exception to caller. throw ex; }? finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
重点看registerBeanPostProcessors//注册拦截bean创建的bean处理器,
可以看到有6类Bean处理器被加载,其中就有AutowiredAnnotationBeanPostProcessor。
再看finishBeanFactoryInitialization(beanFactory);//实例化所有剩余的非延迟加载的单实例,跟着序列图进入下一步:
beanFactory.preInstantiateSingletons();//实例化所有剩余的非延迟加载的单实例。
在这里debug一下,可以看到配置了car的bean和没配置car的bean,容器加载的区别,没配置car的情况下,除了自身的6个Bean,加上我的测试配置有12个bean:
配置了car之后,显示13个bean:
一层层调用到AbstractAutowireCapableBeanFactory.doCreateBean();//创建Bean
这个方法核心逻辑有两处:
1、populateBean(beanName,mbd, instanceWrapper)//设置Bean属性
上面报错的地方就是在populateBean流程中调用AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject方法中抛的错。因为测试类TxnRouteServiceTest有一个自动注入的属性car,而我没有以任何方式配置car的bean,所以初始化TxnRouteServiceTest的时候就会报NoSuchBeanDefinitionException:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.bill99.bean.Car] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
从AutowiredAnnotationBeanPostProcessor的构造函数可以看出,这个解析器主要解析Autowired.class和Value.class的注解:
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
}
debug调用栈信息如下:
2、initializeBean()//初始化Bean
initializeBean包含以下三部分:
{
applyBeanPostProcessorsBeforeInitialization//执行Bean初始化之前的操作,比如@PostConstruct注解标记的初始化方法
invokeInitMethods//执行Bean初始化
applyBeanPostProcessorsAfterInitialization//执行Bean初始化之后的操作
}
现在猜测一下@PostConstruct和@PreDestroy是哪个处理器在处理?因为这个跟初始化和销毁有关,我们顺着这个猜测,可以先看看是不是InitDestroyAnnotationBeanPostProcessor解析,发现不是它解析,看它的子类,最后定位到是CommonAnnotationBeanPostProcessor在处理:
public CommonAnnotationBeanPostProcessor() {
this.setOrder(2147483644);
this.setInitAnnotationType(PostConstruct.class);
this.setDestroyAnnotationType(PreDestroy.class);
this.ignoreResourceType("javax.xml.ws.WebServiceContext");
}
以上就是对@Autowired注解的解析过程粗略的跟读,按此方法同样的可以分析Spring对其他注解的解析。
本文暂时没有评论,来添加一个吧(●'◡'●)