加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[转]Spring注解扫描原理1/2

(2022-04-22 11:29:10)
分类: JAVA开发

原文:https://www.it610.com/article/1495559602308186112.htm


Spring注解扫描原理浅析

二、测试代码

public static void main(String[] args) {

 

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

// 这里可以注册一些配置类

    // applicationContext.register(MyConfig.class);

applicationContext.refresh();

}

三、源码探究

1、ConfigurationClassPostProcessor 的注册

点进AnnotationConfigApplicationContext的空构造函数,可以看到下面的代码

public AnnotationConfigApplicationContext() {

// new了一个Reader

this.reader = new AnnotatedBeanDefinitionReader(this);

// new了个Scanner

this.scanner = new ClassPathBeanDefinitionScanner(this);}

进入new AnnotatedBeanDefinitionReader(this)

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {

this(registry, getOrCreateEnvironment(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)方法

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {

    registerAnnotationConfigProcessors(registry, null);}

继续往里走,就回到达我们的目的地

public static Set registerAnnotationConfigProcessors(

        BeanDefinitionRegistry registry, @Nullable Object source) {

     // 省略...   

     

    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {

        // 创建ConfigurationClassPostProcessor.class对应的BeanDefinition

        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

        def.setSource(source);

        // 注册BeanDefinition

        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

    }

    

// 省略...}

正如你所见,在这个方法中,Spring往容器中事先注册了许多的Bean,其中ConfigurationClassPostProcessor这个Bean是和我们注解的扫描息息相关的

2、ConfigurationClassPostProcessor 的功能

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,

    PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

    // 省略...}

进入ConfigurationClassPostProcessor这个类可以很清晰的看到,它实现了一个BeanDefinitionRegistryPostProcessor接口,接着我们进入到这个接口中去

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

 

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

通过代码可以看到它是接口BeanFactoryPostProcessor的子类

public interface BeanFactoryPostProcessor {

 

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

其这个接口就只有一个方法。请记住现在这个方法,一会儿后面会解释为什么这个类那么重要

3、refresh() —— 启动方法

现在,进入到之前测试代码中的refresh()方法中,这个方法是用于启动容器的,现在我们来看一下它的总体流程

@Overridepublic void refresh() throws BeansException, IllegalStateException {

    synchronized (this.startupShutdownMonitor) {

 

    // 省略...

 

    try {

 

        // 调用一系列的BeanFactoryPostProcessor对Bean工厂进行后置处理

        // 实例化并调用所有已注册的 BeanFactoryPostProcessor bean

        // 会先执行所有 BeanDefinitionRegistryPostProcessors 类中的方法,这个是BeanFactoryPostProcessor的子类

        // Invoke factory processors registered as beans in the context.

        invokeBeanFactoryPostProcessors(beanFactory);

 

 

        // 省略...

    }

 

// 省略...}

这个方法中,我们只需要关注invokeBeanFactoryPostProcessors这一个方法,接下来我们进入其中一探究竟

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {

    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

 

    // 省略...}

通过翻译注释,我们可以知道,这个方法会注册所有实现了BeanFactoryPostProcessor接口的bean,接着继续深入。下面的方法可能会比较长,但是就一个

public static void invokeBeanFactoryPostProcessors(

ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

 

// 保存了已经执行过的BeanDefinitionRegistryPostProcessor

// 目的是防止重复执行

// Invoke BeanDefinitionRegistryPostProcessors first, if any.

Set processedBeans = new HashSet<>();

 

// 如果实现了BeanDefinitionRegistry

if (beanFactory instanceof BeanDefinitionRegistry) {

BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

// 存放所有找出来的BeanFactoryPostProcessor(父类)

List regularPostProcessors = new ArrayList<>();

// 找出所有BeanDefinitionRegistryPostProcessor(子类)

List registryProcessors = new ArrayList<>();

 

// 遍历用户通过API往容器添加的BeanFactoryPostProcessor对象

for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {

if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {

BeanDefinitionRegistryPostProcessor registryProcessor =

(BeanDefinitionRegistryPostProcessor) postProcessor;

// 如果是子类就直接执行postProcessBeanDefinitionRegistryf方法

registryProcessor.postProcessBeanDefinitionRegistry(registry);

registryProcessors.add(registryProcessor);

}

else {

regularPostProcessors.add(postProcessor);

}

}

 

// Do not initialize FactoryBeans here: We need to leave all regular beans

// uninitialized to let the bean factory post-processors apply to them!

// Separate between BeanDefinitionRegistryPostProcessors that implement

// PriorityOrdered, Ordered, and the rest.

List currentRegistryProcessors = new ArrayList<>();

 

// 通过翻译注释可以知道,此处会调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors,通过前面的代码可以知道,

            // Spring内置的ConfigurationClassPostProcessor是实现了的,并且只有它实现了,所以此处的size = 1

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.

String[] postProcessorNames =

beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {

// 实现联动PriorityOrdered接口最优先执行

if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

// 实例化,并放入单例池中

currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

}

}

// 对实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors进行排序

sortPostProcessors(currentRegistryProcessors, beanFactory);

registryProcessors.addAll(currentRegistryProcessors);

// 先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法

// 在此处调用了接口中的postProcessBeanDefinitionRegistry方法

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();

 

// 这里需要再次去容器中获取是因为在上一步过后,容器中可能注册了新的BeanDefinitionRegistryPostProcessors

             // 现在调用的是实现了Ordered接口的容器中可能注册了新的BeanDefinitionRegistryPostProcessors

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.

postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {

// Ordered仅次于POrdered执行

if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {

currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

}

}

// 不难看出执行顺序是PriorityOrdered -> Order -> 普通的,即使前面又注册了新的实现了PriorityOrdered的,在排序后,PriorityOrdered一定会优先执行

// 每次执行都会优先执行实现了POrder接口的

sortPostProcessors(currentRegistryProcessors, beanFactory);

registryProcessors.addAll(currentRegistryProcessors);

// 再调用所实现了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();

 

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.

boolean reiterate = true;

// 因为可能会出现Registry注册Registry这样的套娃情况,所以用了while-true

while (reiterate) {

reiterate = false;

// 如果容器中还有BeanDefinitionRegistryPostProcessor就再循环一边

postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

for (String ppName : postProcessorNames) {

if (!processedBeans.contains(ppName)) {

currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

processedBeans.add(ppName);

reiterate = true;

}

}

sortPostProcessors(currentRegistryProcessors, beanFactory);

registryProcessors.addAll(currentRegistryProcessors);

// 最后调用再调用两个几口都没实现的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

currentRegistryProcessors.clear();

}

 

// 调用BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法,因为这个Registry接口继承了BeanFactoryPostProcessor

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.

// 先调用子类的

invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

// 再调用父类的(API提供的)

invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

}

 

else {

// 调用BeanFactoryPostProcessor接口的postProcessBeanFactory(beanFactory)方法

// Invoke factory processors registered with the context instance.

invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);

}

 

// 执行扫描出来的(父类)

// Do not initialize FactoryBeans here: We need to leave all regular beans

// uninitialized to let the bean factory post-processors apply to them!

String[] postProcessorNames =

beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

 

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,

// Ordered, and the rest.

List priorityOrderedPostProcessors = new ArrayList<>();

List orderedPostProcessorNames = new ArrayList<>();

List nonOrderedPostProcessorNames = new ArrayList<>();

for (String ppName : postProcessorNames) {

if (processedBeans.contains(ppName)) {

// skip - already processed in first phase above

}

else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

// getBean会进行实例化

priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));

}

// 后面只保存了Bean的名字,并没有先实例化,可能是因为BD会被上面实现了PriorityOrdered的BD修改

else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {

orderedPostProcessorNames.add(ppName);

}

else {

nonOrderedPostProcessorNames.add(ppName);

}

}

 

// 最先调用实现了PriorityOrdered的BeanFactoryPostProcessors中的postProcessBeanFactory方法

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.

sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

 

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.

List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());

for (String postProcessorName : orderedPostProcessorNames) {

orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));

}

sortPostProcessors(orderedPostProcessors, beanFactory);

// 再调用实现了Ordered接口的BeanFactoryPostProcessor中的postProcessBeanFactory方法

invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

 

// 最后才调用普通的BeanFactoryPostProcessor的方法

// Finally, invoke all other BeanFactoryPostProcessors.

List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());

for (String postProcessorName : nonOrderedPostProcessorNames) {

nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));

}

invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

 

// 因为上面的BeanFactoryPostProcessor都执行完之后可能会对一些BeanDefinition进行了修改操作,因此讲MergedBD都标记为已已过期的

// Clear cached merged bean definitions since the post-processors might have

// modified the original metadata, e.g. replacing placeholders in values...

beanFactory.clearMetadataCache();

}

**小结:**总结一下这个方法,首先会根据PriorityOrdered -> Ordered-> 没实现这两个接口 这样的顺序去调用所有BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry方法,最后会调用所有BeanFactoryPostProcessorpostProcessBeanFactory方法。换句话说,上面提到的ConfigurationClassPostProcessor因为实现了这两个接口,所以这两个方法都会被调用。接下来我们去看看这个接口里面都是一些什么内容吧!


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有