Spring源码-invokeBeanFactoryPostPr

2021-05-03  本文已影响0人  Wannay

1.invokeBeanFactoryPostProcessors方法的源码

invokeBeanFactoryPostProcessors方法的代码如下

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

但是其真实的逻辑其实在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法中。

2.关于BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor和ConfigurationClassPostProcessor之间的关系

在这个方法中会涉及到几个概念,叫BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor和ConfigurationClassPostProcessor。

2.1我们来看BeanDefinitionRegistryPostProcessor的继承关系

在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法中会涉及到几个概念,叫BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor和ConfigurationClassPostProcessor。

我们来看BeanDefinitionRegistryPostProcessor的继承关系

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor

我们可以看到BeanDefinitionRegistryPostProcessor其实是BeanFactoryPostProcessor的子接口。

2.2 我们再来看一个类ConfigurationClassPostProcessor的继承关系

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware

我们可以看到ConfigurationClassPostProcessor实现了PriorityOrdered接口和BeanDefinitionRegistryPostProcessor接口。

3.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

第一行代码是一个HashSet,名叫processedBeans,顾名思义,就是用来保存已经处理过的Bean(BeanFactoryPostProcessor)的Name。在后面的代码中可以用来避免PostProcessor的Bean被重复调用,每次添加到对应的列表中,都会先判断是否已经在这个Set中。

Set<String> processedBeans = new HashSet<>();

接着是这样的代码,想要拿到BeanDefinitionRegistryPostProcessor的实现类。

//判断beanFactory是否是BeanDefinitionRegistry的实例
if (beanFactory instanceof BeanDefinitionRegistry) {  
    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; 

如果BeanFactory是BeanDefinitionRegistry的实例,就将BeanFactory转换成BeanDefinitionRegistry。

接着,是两个List,regularPostProcessors用来保存普通的BeanFactoryPostProcessor的实现类(Bean),registryProcessors则是保存BeanDefinitionRegistryPostProcessor的实现类(Bean)。

List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

看接下来的代码,这段代码主要用来判断它是不是BeanDefinitionRegistryPostProcessor,如果是,就调用postProcessBeanDefinitionRegistry方法(这个方法就是子接口BeanDefinitionRegistryPostProcessor实现的,并不是BeanFactory接口提供的),并把它放在registryProcessors列表中;如果不是,就把它放在regularPostProcessors列表中。遍历beanFactoryPostProcessors的列表,但是这里一般好像beanFactoryPostProcessors里都没东西,不用遍历。

那么Spring为什么要加这个逻辑呢?其实这是Spring作为一个框架留给我们的扩展点,我们可以手动往beanFactoryPostProcessors这个集合中添加一些BeanFactoryPostProcessor,让这些BeanFactoryPostProcessor在Spring内置的BeanFactoryPostProcessor执行之前就被执行。比如下面这段代码就会在Spring执行内置的BeanDefinitionRegistryPostProcessor之前先去执行我们自定义的BeanDefinitionRegistryPostProcessor的逻辑。

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }

那么我们如何往这里添加BeanDefinitionRegistryPostProcessor,让它在这里就执行呢?我们可以使用如下的方式去手动添加。

        //这里要使用AnnotationConfigApplicationContext去创建,不能使用ApplicationContext接口去创建
        //因为addBeanFactoryPostProcessor方法是在AnnotationConfigApplicationContext中实现的
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(App.class);  //手动注册
        context.addBeanFactoryPostProcessor(new MyBeanDefinitionRegistryPostProcessor());
        context.refresh();

这段代码是不是很熟悉?

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        this();
        register(componentClasses);
        refresh();
    }

其实这就和我们传入一个componentClasses参数的方式很类似,我们只不过在refresh方法执行之前往容器中加入了我们自定义的BeanFactoryPostProcessor。


image.png

我们可以看到,我们自己加进去的PostProcessor在这里就已经能拿到了。这样,我们就成功添加了我们自己的PostProcessor,在Spring执行内置的PostProcessor之前,就会先执行我们自己先加进去的方式。

接下来是一个列表currentRegistryProcessors,这个列表中来存放当前正在执行的BeanDefinitionRegistryPostProcessor。

List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

接着是这样一段代码,这段代码主要是拿到BeanDefinitionNames作为Key,再通过BeanDefinitionMap拿到BeanDefinition的Class是否实现了BeanDefinitionRegistryPostProcessor接口,如果实现了那么就将Key加入到postProcessorNames中,再根据BeanDefinitionName去BeanFactory中拿BeanDefinition,看它是否实现了PriorityOrdered接口。在invokeBeanDefinitionRegistryPostProcessors方法中则将这些PostProcessor进行实例化,调用getBean-doGetBean-createBean-doCreateBean一系列的方法去创建PostProcessor的Bean并进行执行。

            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            //这里会执行Spring内置的PostProcessor--->
            //ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
            //执行这里之后就会将我们自己实现的BeanRegistryPostProcessor扫描进来
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            //清除列表,避免重复执行
            currentRegistryProcessors.clear();

需要注意的是使用如下的方式去拿到BeanFactory,由于构造方法中就执行了scan(basePackages)这个方法,将BeanDefinition已经加载到BeanDefinitionMap中。

ApplicationContext context = new AnnotationConfigApplicationContext("com.wanna.bean");

如果是使用的如下方式去拿到BeanFactory,则是在refresh方法的第二步执行的obtainFreshBeanFactory方法中将BeanDefinition加载到BeanFactory中的。

ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");

如果是使用的是如下方式去拿到BeanFactory,则是在 invokeBeanDefinitionRegistryPostProcessors这个方法中的postProcessor.postProcessBeanDefinitionRegistry(registry)这个步骤才将非Spring内置的BeanDefinition加载到BeanFactory中。使用这种方式在调用之前,BeanFactory中只有ConfigurationClassPostProcessor这一个BeanDefinition的Class是实现了PriorityOrdered接口的。在执行invokeBeanDefinitionRegistryPostProcessors时,调用的ConfigurationClassPostProcessor这个类的postProcessBeanDefinitionRegistry方法将用户自定义的BeanDefinition扫描进来。但是如果是使用另外的两种方式,这里调用之前就已经可以拿到我们自定义的BeanDefinitionRegistryPostProcessor的BeanDefinition了

ApplicationContext context = new AnnotationConfigApplicationContext(App.class)

也就是到这里,无论哪种方式都已经将BeanDefinition加载到BeanFactory中,后面要用到只需要拿来进行创建Bean即可。

在invokeBeanDefinitionRegistryPostProcessors方法中还会将实现了PriorityOrdered接口的Bean给创建出来并执行postProcessBeanDefinitionRegistry。也就是如果我们自定义如下的BeanDefinitionRegistryPostProcessor,也会在这里执行postProcessBeanDefinitionRegistry方法,打印Wanna--postProcessBeanDefinitionRegistry这句话。

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("Wanna-postProcessBeanFactory");
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("Wanna--postProcessBeanDefinitionRegistry");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

接下来这段代码和上面的类似,只不过这里是调用的是实现了BeanDefinitionRegistryPostProcessor和Ordered接口的实现类(Bean)。在invokeBeanDefinitionRegistryPostProcessors方法中则将这些PostProcessor进行实例化,调用getBean-doGetBean-createBean-doCreateBean一系列的方法去创建PostProcessor的Bean并进行执行。

            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();

下面段代码也是很类似,调用的是实现了BeanDefinitionRegistryPostProcessor接口,但是没实现Ordered接口和PriorityOrdered接口的实现类(Bean)。在invokeBeanDefinitionRegistryPostProcessors方法中则将这些PostProcessor进行实例化,调用getBean-doGetBean-createBean-doCreateBean一系列的方法去创建PostProcessor的Bean并进行执行。

            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                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);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
                currentRegistryProcessors.clear();
            }

接着,下一段,这里第一个方法会调用BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(需要说明的是,BeanDefinitionRegistryPostProcessor这个接口有两个方法,一个来自于BeanFactoryPostProcessor,另一个来自于BeanDefinitionRegistryPostProcessor自己实现的,上面调用的都只是postProcessBeanDefinitionRegistry方法,而这里调用的是postProcessBeanFactory方法),也就是Wanna-postProcessBeanFactory这句话会在第一个方法执行完之后打印,regularPostProcessors一般为null。在上面我们讲了会在执行Spring内置的BeanDefinitionRegistryPostProcessor之前可以执行我们自己使用API方式定义的BeanDefinitionRegistryPostProcessor。而这里调用的第二个方法其实就是保证我们使用API方式往容器中加入的普通BeanFactoryPostProcessor能够先执行,再执行其他的BeanFactory。

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

下面一大段代码也是类似,只不过这里执行的是并没有实现BeanDefinitionRegistryPostProcessor,仅仅实现了普通BeanFactoryPostProcessor接口的实现类。也是依次执行实现了PriorityOrdered接口、Ordered接口、既没有实现PriorityOrdered又没有实现Ordered接口的实现类。利用BeanDefinition进行实例化,并调用postProcessBeanFactory方法。

        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        // 2.将实现了PriorityOrdered、Ordered接口的BeanFactoryPostProcessor和剩下的分开并进行调用
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> 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)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            } else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        // 2.1将实现了PriorityOrdered接口的BeanFactoryPostProcessor进行排序并进行调用
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        // 2.2将实现了Ordered接口的BeanFactoryPostProcessor进行排序并调用
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        // 2.3调用既没有实现PriorityOrdered接口、也没有实现Ordered的BeanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
上一篇下一篇

猜你喜欢

热点阅读