在之前的springboot 启动bean加载处理器ConfigurationClassPostProcessor系列文章中,只是介绍了它的作用。那么这里有以下几个问题:
- ConfigurationClassPostProcessor 什么时候加载到spring容器中?
- ConfigurationClassPostProcessor 是什么时候起作用的?
- 为什么会先执行postProcessBeanDefinitionRegistry方法,然后再执行postProcessBeanFactory的呢?
springboot在启动准备好环境environment《springboot启动之配置文件秘密》,会进入ApplicationContext相关流程
public class SpringApplication {
...
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//进入ApplicationContext相关流程,首先是创建
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
+ "annotation.AnnotationConfigApplicationContext";
/**
* The class name of application context that will be used by default for web
* environments.
*/
public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
+ "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";
/**
* The class name of application context that will be used by default for reactive web
* environments.
*/
public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
+ "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";
//创建 ApplicationContext,
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
}
不管那种类型,在其构造方法中都会创建一个
this.reader = new AnnotatedBeanDefinitionReader(this);
在AnnotatedBeanDefinitionReader构造方法中
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
会调用AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)方法进行注入AnnotationConfigProcessors
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
这个时候容器中就会存在两个重要的bean,这也就解释了开头的第一个问题
- ConfigurationClassPostProcessor
- AutowiredAnnotationBeanPostProcessor ,这个作用《
springboot启动bean加载处理器ConfigurationClassPostProcessor 二(@PropertySource注解)》
那么第二个问题,是什么时候起作用的?springboot再创建好ApplicationContext,并执行prepareContext方法后,会执行refreshContext,就来到了今天的主角invokeBeanFactoryPostProcessors,这个方法比较长,主要分成两个流程
- 处理BeanDefinitionRegistryPostProcessor实现类
- 处理BeanFactoryPostProcessor实现类
这里要注意BeanDefinitionRegistryPostProcessor 本来就是继承了 BeanFactoryPostProcessor。
先不管逻辑是怎么实现的,开头的第二(是什么时候起作用的)、三(为什么会先执行postProcessBeanDefinitionRegistry方法,然后再执行postProcessBeanFactory的呢)个问题想必已经清楚了。
不能耍流氓是吧,总得出的干货,来先看处理BeanDefinitionRegistryPostProcessor流程
依次对箭头中的方块流程解释下:
- 紫色,invokeBeanFactoryPostProcessors方法的有会获取当前ApplicationContext中的beanFactoryPostProcessors
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
它是在创建好ApplicationContext后执行prepareContext的方法的applyInitializers加入,会执行ApplicationContextInitializer(创建SpringApplication 时候从spring.factories加载,要加载自定义的BeanDefinitionRegistryPostProcessor ,这是个入口)类型的,这里就不展开默认三个类型作用了
- 橙色,这是个重要步骤,执行前会去当前的容器中获取类型为:BeanDefinitionRegistryPostProcessor,当然会获取到ConfigurationClassPostProcessor,在执行postProcessBeanDefinitionRegistry(这里的前提是实现了接口PriorityOrdered),之前分析这个步骤的作用(加载更多的类到容器中)
- 粉色,执行前会去容器中再去取BeanDefinitionRegistryPostProcessor,我们自定义并且实现该接口的就会在这里执行,然后执行实现接口Ordered,区分优先级,注意这里PriorityOrdered优先级已经失效了,因为在上一步已经执行过了,要想实现PriorityOrdered接口功能,可以在紫色步骤。
- 蓝色,执行未实现PriorityOrdered、Ordered,并执行postProcessBeanDefinitionRegistry,这里是个while循环
- 绿色,执行方法postProcessBeanFactory,这里的类型当然是BeanDefinitionRegistryPostProcessor
再继续看下是怎么处理BeanFactoryPostProcessor的?
这个流程相对比较简单,从当前的容器中获取BeanFactoryPostProcessor,过滤掉在上一步已经处理的bean,然后按照PriorityOrdered、Ordered、none进行分组并排序,依次执行priorityOrderedPostProcessors、orderedPostProcessorNames、nonOrderedPostProcessorNames组中的postProcessBeanFactory方法。
总结下:BeanDefinitionRegisterPostProcess、BeanFactoryPostProcess作用,BeanDefinitionRegisterPostProcess可以作为向容器中加载bean处理,例如ConfigurationClassPostProcessor ,BeanFactoryPostProcess可以作为修改加载bean定义属性!
实际操作验证下,我们定义一下几种bean
@Component
public class BeanDefinitionRegisterPostProcessNormal implements BeanDefinitionRegistryPostProcessor{}
@Component
public class BeanDefinitionRegisterPostProcessWithOrdered implements BeanDefinitionRegistryPostProcessor, PriorityOrdered{}
@Component
public class BeanDefinitionRegisterPostProcessWithPriorityOrdered implements BeanDefinitionRegistryPostProcessor, PriorityOrdered{}
@Component
public class BeanFactoryPostProcessWithOrder implements BeanFactoryPostProcessor, Ordered{}
@Component
public class BeanFactoryPostProcessWithPriorityOrder implements BeanFactoryPostProcessor, PriorityOrdered {}
依次输出为:
BeanDefinitionRegisterPostProcessWithOrdered -->postProcessBeanDefinitionRegistry
// 看这个PriorityOrdered优势没了
BeanDefinitionRegisterPostProcessWithPriorityOrdered -->postProcessBeanDefinitionRegistry
BeanDefinitionRegisterPostProcessNormal -->postProcessBeanDefinitionRegistry
BeanDefinitionRegisterPostProcessWithOrdered -->postProcessBeanFactory
BeanDefinitionRegisterPostProcessWithPriorityOrdered -->postProcessBeanFactory
BeanDefinitionRegisterPostProcessNormal -->postProcessBeanFactory
BeanFactoryPostProcessWithPriorityOrder-->postProcessBeanFactory
BeanFactoryPostProcessWithOrder-->postProcessBeanFactory
//这个是自定义实现BeanFactoryPostProcessor,未实现PriorityOrdered、Ordered
UpdateDataSourcePrefix-->postProcessBeanFactory
符合我们分析的逻辑