ConfigurationClassPostProcessor注册时机
首先在AnnotatedBeanDefinitionReader的构造函数中注册
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);
/*
这里很重要 因为ConfigurationClassPostProcessor就是在这里被注入的!
注册了5个
//BeanFactoryPostProcessor
RootBeanDefinition def = new
RootBeanDefinition(ConfigurationClassPostProcessor.class);
//BeanPostProcessor
RootBeanDefinition def = new
RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
//BeanPostProcessor
RootBeanDefinition def = new
RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
//EventListenerMethodProcessor
RootBeanDefinition def = new
RootBeanDefinition(EventListenerMethodProcessor.class);
RootBeanDefinition def = new
RootBeanDefinition(DefaultEventListenerFactory.class);
*/
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
就是注册默认的后置处理器,这个方法跟到底,一直到registerAnnotationConfigProcessors这个方法,这个方法里面就是真正的注册各种内置的后置处理器。
其次在ClassPathBeanDefinitionScanner#scan方法中也做了判断并进行了注册。
/**
* 扫描给定的包路径,生成BeanDefinition并注册到注册器
*/
public int scan(String... basePackages) {
////获取注册器中已注册的bean数量
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
//通过doScan给定包路径并生成BeanDefinition注册到registry中
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
// 这个方法很重要 注册了内置的ConfigurationClassPostProcessor
AnnotationConfigUtils.
registerAnnotationConfigProcessors(this.registry);
}
//返回本次扫描并注册到IOC容器中的类
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
ConfigurationClassPostProcessor源码
在本专题博客(五)中讲解了BeanFactoryPostProcessor及子类BeanDefinitionRegistryPostProcessor,我们讲过spring初始化过程中会默认注册几个后置处理器,在refresh()正式启动spring容器过程中会调用默认注册的后置处理器。
其中有一个后置处理器叫ConfigurationClassPostProcessor。
在sping中扮演着最最最重要的角色,本篇博文我们详细讲解该后置处理器。
自定义的Bean通过配置类被扫描
package tyrant;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class User {
@Bean
public User getUser() {
return new User();
}
private int age = 31;
private String name = "user";
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package tyrant;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
//包扫描
@ComponentScan("tyrant")
//使用xml文件启动
//@ImportResource("applicationContext.xml")
public class Config {
}
public class Test {
public static void main(String[] args) {
//第一种方式 如果没有参数Config.class那么Spring在扫描的时候不会扫描到我们自定义的bean
// AnnotationConfigApplicationContext context = new
// AnnotationConfigApplicationContext(Config.class);
//第二种方式
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext();
//注册配置类
//如果没有下面这句代码 那么Spring在扫描的时候不会扫描到我们自定义的bean
context.register(Config.class);
context.refresh();
BeanDefinition beanDefinition = context.getBeanDefinition("getUser");
//查看spring给我生成的具体BeanDefinition类型
//ConfigurationClassBeanDefinition
System.out.println(beanDefinition.getClass().getSimpleName());
}
}
ConfigurationClassPostProcessor作用
ConfigurationClassPostProcessor是一个BeanFactory的后置处理器。因此它的主要功能是参与BeanFactory的建造,在这个类中,会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解。
ConfigurationClassPostProcessor注册时机
首先在AnnotatedBeanDefinitionReader的构造函数中会被注册
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);
/*
这里很重要 因为ConfigurationClassPostProcessor就是在这里被注入的!
注册了5个
BeanFactoryPostProcessor
RootBeanDefinition def = new
RootBeanDefinition(ConfigurationClassPostProcessor.class);
BeanPostProcessor
RootBeanDefinition def = new
RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
BeanPostProcessor
RootBeanDefinition def = new
RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
EventListenerMethodProcessor
RootBeanDefinition def = new
RootBeanDefinition(EventListenerMethodProcessor.class);
RootBeanDefinition def = new
RootBeanDefinition(DefaultEventListenerFactory.class);
*/
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
这个方法就是注册默认的后置处理器。这个方法跟到底。
一直到registerAnnotationConfigProcessors这个方法,这个方法里面就是真正的注册各种内置的后置处理器。
其次在ClassPathBeanDefinitionScanner#scan方法中也做了判断并进行了注册。
/**
* 扫描给定的包路径并生成BeanDefinition注册到注册器
*/
public int scan(String... basePackages) {
//获取注册器中已注册的bean数量
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
//通过doScan给定包路径并生成BeanDefinition注册到registry中
doScan(basePackages);
//Register annotation config processors,if necessary
//includeAnnotationConfig 默认值是true
if (this.includeAnnotationConfig) {
//这个方法很重要 注册了内置的ConfigurationClassPostProcessor
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
//返回本次扫描并注册到IOC容器中的类
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);和上面一样,不赘述。
ConfigurationClassPostProcessor调用时机
在完成spring的启动过程,会调用context.refresh();。
根据context.refresh();找到这行代码invokeBeanFactoryPostProcessors(beanFactory)。
调用所有注册的beanFactory后置处理器,继续跟进去:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//getBeanFactoryPostProcessors获取后置处理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
跟进第一行代码invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
这个方法实现了spring后置处理器的调用,包括spring内置的处理器和程序员自定义的处理器。
ConfigurationClassPostProcessor调用时机。
需要在invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
往下找到下面的代码:
//查询BeanDefinitionRegistryPostProcessor的实现类
//获取到的是internalConfigurationAnnotationProcessor
//其实是一个ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType
(BeanDefinitionRegistryPostProcessor.class, true, false);
//先放入优先级高的
//即实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//添加到数组中,后续进行遍历回调
currentRegistryProcessors
.add(beanFactory.getBean(ppName,
BeanDefinitionRegistryPostProcessor.class));
//存储BeanDefinitionRegistryPostProcessor实现类的名字
processedBeans.add(ppName);
}
}
//对BeanDefinitionRegistryPostProcessor设置调用顺序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//执行BeanDefinitionRegistryPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
这段代码就是完成ConfigurationClassPostProcessor后置处理器的调用!
首先,查找实现BeanDefinitionRegistryPostProcessor接口的bean,这里其实就有一个,就是ConfigurationClassPostProcessor。
然后判断是否实现了PriorityOrdered接口,ConfigurationClassPostProcessor确实实现了这个接口,然后放到集合中。
最后在invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);完成ConfigurationClassPostProcessor的调用,我们看下这个方法:
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
//for循环调用
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
没错,先调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法。 后续代码继续调用ConfigurationClassPostProcessor的postProcessBeanFactory方法。
Spring在启动过程中,最先调用的是ConfigurationClassPostProcessor后置处理器,该处理器通过以上两个方法完成扫描和注册BeanDefinition。
为什么只会找到内置的处理器?
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>)方法中,有这么一句代码。
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
getBeanNamesForType看方法名:意思为指定类型的class找到Bean对应的Name并返回。
为什么只会找到内置的处理器ConfigurationClassPostProcessor呢?
如果我们自定义了BeanFactoryPostProcessor会被找到吗?
不会。
源码之下无秘密,直接跟进源码:
DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class\<?>, boolean, boolean)
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
//跟进这里
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<>();
/***
this.beanDefinitionNames = {ArrayList@1457} size = 8
0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
3 = "org.springframework.context.event.internalEventListenerProcessor"
4 = "org.springframework.context.event.internalEventListenerFactory"
5 = "config"
6 = "user"
7 = "userService
***/
for (String beanName : this.beanDefinitionNames) {
//代码略
//判断是否匹配
boolean matchFound =
//第一个条件
(allowEagerInit || !isFactoryBean || (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
//第二个条件
(includeNonSingletons ||(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
//第三个条件
isTypeMatch(beanName, type);
//代码略
}
/****
this.manualSingletonNames = {LinkedHashSet@1482} size = 3
0 = "environment"
1 = "systemProperties"
2 = "systemEnvironment"
****/
for (String beanName : this.manualSingletonNames) {
//代码略
}
return StringUtils.toStringArray(result);
}
省略了部分代码。
逻辑是遍历beanDefinitionNames,matchFound标志位根据3个条件判断是否匹配。
最重要的是第三个条件:BeanDefinition对应的Class的类型和要查询的类型是否匹配。
如果匹配就返回BeanName。
ConfigurationClassPostProcessor类继承关系
ConfigurationClassPostProcessor实现了 BeanDefinitionRegistryPostProcessor接口。BeanDefinitionRegistryPostProcessor接口又继承了 BeanFactoryPostProcessor接口。
所以ConfigurationClassPostProcessor中需要重写 1.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry()方法2.BeanFactoryPostProcessor#postProcessBeanFactory() 方法。
而ConfigurationClassPostProcessor类的作用就是通过这两个方法去实现的。
ConfigurationClassPostProcessor核心方法
上文讲过,spring启动过程中
先调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry(registry)
再调用ConfigurationClassPostProcessor的postProcessBeanFactory(beanFactory)
我们来详细讨论这两个方法完成的功能。