1. 知识准备:
1.1 AnnotationConfigUtils
在读取beanDefination的时候,调用自定义的解析器,对于AnnotationConfigBeanDefinitionParser和ComponentScanBeanDefinitionParser会调用AnnotionCOnfigUtils.java 的registerAnnotationConfigProcessors,把beanName注册进去。
//==================
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor...
AnnotationConfigUtils.java
{
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
.. ..
// 注册内部管理的用于处理@configuration注解的后置处理器的bean
//****************重点*****************
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(..){
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 注册BeanDefinition到注册表中 。ConfigurationClassPostProcessor到注册表中(以后可以实例化了)
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
.....
}
}
1.2 调用时机
其中第一和第二,是处理xml配置(component-scan和annotation-config)的时候,注册bfpp等定义信息的。第三种是注解启动时候注册各种bd信息的。
==========================注解工具注册====================
调用registerAnnotationConfigProcessors(..)注册bd
// 根据条件,选择注册bean的定义信息
1. ConfigurationClassPostProcessor(bfpp)
2. AutowiredAnnotationBeanPostProcessor(bpp)
3. CommonAnnotationBeanPostProcessor(bpp)
4. EventListenerMethodProcessor(bfpp)
5. DefaultEventListenerFactory 等
在下面三个地方调用了:
1.
//registerBeanDefinitionParser("annotation-config", new //AnnotationConfigBeanDefinitionParser());
AnnotationConfigBeanDefinitionParser.java#parse{
//注册注解配置处理器 bean信息
Set<BeanDefinitionHolder> processorDefinitions =
//注册bfpp和bpp
AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source);
}
//根据标签解析。注册解析器
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
2.
//处理 <component:scan base-package.. 等xml 配置
// registerBeanDefinitionParser("component-scan", new //ComponentScanBeanDefinitionParser());
ComponentScanBeanDefinitionParser.java#parse{
ClassPathBeanDefinitionScanner#doScan();
// 把扫描到的bd放进容器
// 注册系统bd信息
AnnotationConfigUtils.registerAnnotationConfigProcessors(..)
}
3.本类 registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
3.1 使用注解启动的时候,使用的。AnnotationConfigApplicationContext启动的
//在构造方法中调用了
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
// 。。。
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
2. 源码分析
2.1 开始
refresh()
-> invokeBeanFactoryPostProcessors
// 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName
String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//实例化bfpp
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
...
//调用
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
->
PostProcessorRegistrationDelegate.java postProcessor.postProcessBeanDefinitionRegistry(registry);
到达:ConfigurationClassPostProcessor.java
类
// 定位、加载、解析、注册相关注解
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//....
processConfigBeanDefinitions(registry);
}
到达ConfigurationClassPostProcessor.java
类
/**
* 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作
* 获取所有的beanDefination对象,然后遍历,查看这些类上面的注解
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition
//被@Component已经注册过了
for (String beanName : candidateNames) {
do {
// 解析带有@Controller、@Import、@ComponentScan、@Bean的BeanDefinition
// ConfigurationClassParser parser
parser.parse(candidates);
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
this.reader.loadBeanDefinitions(configClasses);
}
}
转移到ConfigurationClassParser.java
类。核心处理方法在doProcessConfigurationClass()
中。
=======>ConfigurationClassParser.java#parse(..){
//根据不同的类型,调用重载的parse方法
}
以注解为例子
->parse()
-->processConfigurationClass()
--->doProcessConfigurationClass(){
//1. 递归处理内部类,符合条件的加入到候选。遍历处理
2. 处理@PropertySource 注解
3. 处理处理@ComponentScan或者@ComponentScans注解,通过ComponentScanAnnotationParser#parse(..),进而调用ClassPathBeanDefinitionScanner#doScan(..),解析的是@Component及其子类,解析到了所有的scannedBeanDefinitions,判断是,是不是配置类,是配置类,再递归处理
4. 处理@Import注解
5. 处理@ImportResource注解
6. 处理@Bean注解的方法
7. 处理接口,jdk8支持接口@Bean注解
}
// 到此,注解解析完毕
2.2 源码流程
AbstractApplicationContext.java#invokeBeanDefinitionRegistryPostProcessors
-》PostProcessorRegistrationDelegate.java#invokeBeanDefinitionRegistryPostProcessors
-》PostProcessorRegistrationDelegate.java#postProcessor(ConfiguratiionClassPostProcessor).postProcessBeanDefinitionRegistry(registry);
-》ConfiguratiionClassPostProcessor.java#processConfigBeanDefinitions(registry);
-》ConfiguratiionClassPostProcessor.java#parser.parse(candidates);这里的parser就是ConfigurationClassParser类型,解析完,从列表bd放到工厂中;
-》ConfigurationClassParser.java#processConfigurationClass(…);这里放到列表中
-》ConfigurationClassParser.java#doProcessConfigurationClass(…),这里开始解析各种注解,然后configurationClasses.put(configClass, configClass);这里是将
@Import注解标记的普通类,放到列表,@ComponentScan扫描到的被标记的,然后调用processConfigurationClass()
-》