Spring Ioc源码分析系列–Ioc容器BeanFactoryPostProcessor后置处理器分析

Spring Ioc源码分析系列–Ioc容器BeanFactoryPostProcessor后置处理器分析

前言

上一篇文章Spring Ioc源码分析系列–Ioc源码入口分析已经介绍到Ioc容器的入口 refresh()方法,并且分析了 refresh()方法里面的前三个子方法分析了一下。还记得分析了什么麽?估计早忘了分析了什么,可以说是看了个寂寞。但是不要慌,看了忘肯定是正常的,需要回顾复习一下,最好做点笔记记录一下,有自己的沉淀才会印象深刻。最好跟着代码自己调试几遍, 纸上得来终觉浅,绝知此事要躬行

好了,这里回顾一下上篇文章的内容。上篇文章主要分析了三个方法, prepareRefresh()进行了一些容器启动前的属性设置, obtainFreshBeanFactory()方法完成了读取配置文件,该方法的实现会针对xml配置创建内部容器,该容器负责bean的创建与管理,会进行 BeanDefinition的注册, prepareBeanFactory(beanFactory)方法主要注册一些容器中需要使用的系统 bean,例如 classloaderBeanFactoryPostProcessor等。

喝了鸡汤看了回顾,接下来才是今天这篇文章的正文开始。

思考一个问题, Spring提供了非常良好的扩展性,那么扩展性在哪里体现?这个问题仁者见仁智者见智,但是把场景压缩一下,压缩到上一篇文章我们已经获得了一个加载完成 BeanDefinition的容器上,我在统一的 BeanDefinition加载完成后,我想修改某一个或者增加某一个 BeanDefinition这时候怎么实现呢?

对Spring熟悉点的读者可能已经猜到,这时候就可以使用 BeanFactoryPostProcessor后置处理器来完成这个操作了,那么这篇文章会解决两个疑问:

  • BeanFactoryPostProcessor是什么以及如何使用?
  • BeanFactoryPostProcessor在源码里的调用逻辑?

第一个疑问会通过一个例子来说明,第二个疑问会通过源码分析来阐述。废话少说,先进行 BeanFactoryPostProcessor介绍,然后还是使用上一篇文章的例子来实现用 BeanFactoryPostProcessor来替换 UserService的实现。

BeanFactoryPostProcessor介绍

这是一个容器的钩子方法,允许自定义修改应用程序上下文的 bean 定义,调整上下文底层 bean 工厂的 bean 属性值。对于针对用系统管理员的自定义配置文件覆盖应用程序上下文中配置的 bean 属性非常有效。 BeanFactoryPostProcessor可以与 bean 定义交互和修改,但不能与 bean 实例交互。这样做可能会导致过早的 bean 实例化,违反容器并导致意外的副作用。如果需要 bean 实例交互,请考虑改为实现 BeanPostProcessorApplicationContext 自动检测其 bean 定义中的 BeanFactoryPostProcessor ,并在创建任何其他 bean 之前应用它们。 BeanFactoryPostProcessor 也可以通过编程方式注册到 ConfigurableApplicationContext

这个类只有一个方法,入参为当前容器,下面来看一下 postProcessBeanFactory()这个方法。

@FunctionalInterface
public interface BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     *
     * 在标准初始化之后修改应用程序上下文的内部 bean 工厂。
     * 所有 bean 定义都将被加载,但还没有 bean 被实例化。
     * 这允许覆盖或添加属性,甚至是急切初始化的 bean。
     *
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

可以看到这里的操作空间是非常大的,直接把当前的容器传入, 意味着你可以在当前容器的基础上做任何操作。就比如你天天看着女神,可望而不可即,但是某天通过一个传送门,把女神送到了你家里,你是不是可以为所欲为了,想干什么就干什么,例如你可以让她穿你喜欢的衣服,吃你喜欢吃的东西等等。

代码例子

那下面就用代码实现一下。还是在上一篇文章Spring Ioc源码分析系列–Ioc源码入口分析的基础上进行添加代码, 所有源码都可以在我的仓库ioc-sourcecode-analysis-code-demo里找到 。

首先新建一个 ReplaceUserServiceImpl类实现 UserService

/**
 * @author Codegitz
 * @date 2022/5/12 15:57
 **/
public class ReplaceUserServiceImpl implements UserService {
    @Override
    public User getUser(String name, String age) {
        User user = new User();
        user.setId("1");
        // 这里更改了赋值
        user.setName("ReplaceUser-" + name);
        user.setAge(age);
        return user;
    }
}

接着用一个类实现 BeanFactoryPostProcessor。可以看到我这里的逻辑也非常简单,就是判断是否存在一个名为 userServiceBeanDefinition,如果有则把它的实现替换为 io.codegitz.service.impl.ReplaceUserServiceImpl

/**
 * @author Codegitz
 * @date 2022/5/12 16:01
 **/
public class ReplaceUserBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (beanFactory.containsBeanDefinition("userService")){
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
            beanDefinition.setBeanClassName("io.codegitz.service.impl.ReplaceUserServiceImpl");
        }
    }
}

后置处理器已经准备好,接下来把后置处理器注册到容器里,我代码例子采用的是 xml方式。


到这里一切都完成了,那么就可以启动引导类跑一下看看效果了。可以看到这里的实现已经替换为 ReplaceUserServiceImpl,说明我们的 ReplaceUserBeanFactoryPostProcessor后置处理器是生效了,那么是怎么生效的呢?进入下一节的源码分析。

Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

源码分析

上面已经通过一个例子实现了功能,那么这个源码里是怎么实现的呢?这里会衔接上一篇文章的源码分析,继续在 refresh()方法里游荡。上一篇已经分析了前三个,这篇会继续往下分析两个方法,分别是 postProcessBeanFactory(beanFactory)invokeBeanFactoryPostProcessors(beanFactory)invokeBeanFactoryPostProcessors(beanFactory)就是后置处理器的逻辑,衔接了上文的例子。好家伙,互相衔接。

postProcessBeanFactory(beanFactory)

这是一个空方法,留给子类实现,主要是一些 web相关的 ApplicationContext会重写这个方法,传入的是当前容器,操作空间也是非常大的。由于是个空方法,这里不再赘述。

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for registering special
     * BeanPostProcessors etc in certain ApplicationContext implementations.
     *
     * 在标准初始化之后修改应用程序上下文的内部 bean 工厂。
     * 所有 bean 定义都已经被加载,但还没有 bean 被实例化。
     * 这允许在某些 ApplicationContext 实现中注册特殊的 BeanPostProcessors 等。
     *
     * @param beanFactory the bean factory used by the application context
     */
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

invokeBeanFactoryPostProcessors(beanFactory)

接下来就进入了今天的重头戏,跟进代码,可以看到主要的代码实现委托给了 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())去实现。

    /**
     * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
     * respecting explicit order if given.
     * Must be called before singleton instantiation.
     *
     * 实例化并调用所有已注册的 BeanFactoryPostProcessor bean,如果给定顺序,则按照顺序去执行
     * 所有的后置处理器必须在其他的单例bean实例化之前被调用
     */
    //实例化并且调用所有BeanFactoryPostProcessor beans
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 这个方法会进行两种操作
        // 1.把给定的 BeanFactoryPostProcessor 传入执行
        // 2.自动扫描容器里的所有的 BeanFactoryPostProcessor 执行
        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)
        // 检测是否有用于类型匹配的临时 ClassLoader 和 LoadTimeWeaver
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

跟进 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())里面的代码。这个方法比较长,但是逻辑却非常简单,跟着注释看一下理解起来问题不大。

    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set processedBeans = new HashSet<>();

        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            // 常规的BeanFactoryPostProcessor后置处理器
            List regularPostProcessors = new ArrayList<>();
            // 扩展注册BeanDefinition的BeanDefinitionRegistryPostProcessor后置处理器
            List registryProcessors = new ArrayList<>();

            // 根据类型放入不同的后置处理器列表里
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    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.
            // 这里不会初始化FactoryBeans,因为先初始化了的话BeanFactoryPostProcessor就无法对已经初始化的bean生效了
            List currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 首先会调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors
            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);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            // 接下来调用实现了Ordered接口的BeanDefinitionRegistryPostProcessors
            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);
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            // 最后,调用没有实现上述接口的BeanDefinitionRegistryPostProcessors
            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?
                        // 因为这里BeanDefinitionRegistryPostProcessor可能会注册另外的BeanFactoryPostProcessor,
                        // 所以需要循环去迭代,直到当前容器里没有BeanFactoryPostProcessor为止
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                // 这里可能会继续注册BeanFactoryPostProcessor
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            // 前面已经处理完成了所有的 BeanDefinitionRegistryPostProcessor,
            // 接下来这两个方法就是处理 BeanFactoryPostProcessor,
            // 注意这里只是处理了方法传入的 beanFactoryPostProcessors ,
            // 处理完这个后后续的逻辑还是会自动检测当前容器里所有的BeanFactoryPostProcessor,然后分类逐次调用
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            // 如果给定的beanFactory不是BeanDefinitionRegistry,
            // 那么就不需要进行前面调用 BeanDefinitionRegistryPostProcessor 的操作,
            // 直接调用给定的 beanFactoryPostProcessors
            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!
        // 这里的逻辑跟上面的 BeanDefinitionRegistryPostProcessor 处理逻辑类似
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        // 按照不同的优先级去分类 BeanFactoryPostProcessor
        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)) {
                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.
        // 首先调用实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

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

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

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        // 清除缓存的 merged bean definitions 定义,因为后处理器可能已经修改了原始元数据,例如替换值中的占位符...
        beanFactory.clearMetadataCache();
    }

这个方法主要做了以下几件事:

  • 首先会判断当前容器的类型是不是 BeanDefinitionRegistry类型,如果是,则判断 给定的 beanFactoryPostProcessors是否存在 BeanDefinitionRegistryPostProcessor类型的后置处理器,如果有则执行 postProcessBeanDefinitionRegistry()方法,进行 BeanDefinition的注册。接着会分别获取当前容器里实现了 PriorityOrderedOrdered接口和没有实现排序接口的 BeanDefinitionRegistryPostProcessor,排序后依次执行。
  • 如果不是 BeanDefinitionRegistry类型,则直接调用 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory)方法调用所有给定的 BeanFactoryPostProcessor
  • 经过前面两步,已经处理完成了给定了 beanFactoryPostProcessors,这里会去检测执行容器里存在的 BeanFactoryPostProcessor。这里也会按照 PriorityOrderedOrdered接口以及没有实现排序接口的顺序去调用。
  • 最后会清空容器里元数据的配置缓存

这个方法的逻辑是比较简单的,就是代码量比较大,需要耐心看完。

接下来看下里面的一些字方法的内容

sortPostProcessors()完成后置处理器排序

    private static void sortPostProcessors(List postProcessors, ConfigurableListableBeanFactory beanFactory) {
        // 比较简单,就是获取一个比较器 Comparator ,至于 Comparator 的原理,可以自己去看下相关文章
        Comparator comparatorToUse = null;
        if (beanFactory instanceof DefaultListableBeanFactory) {
            comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
        }
        if (comparatorToUse == null) {
            comparatorToUse = OrderComparator.INSTANCE;
        }
        // 排序
        postProcessors.sort(comparatorToUse);
    }

invokeBeanDefinitionRegistryPostProcessors()调用所有的BeanDefinitionRegistryPostProcessor

这个方法也比较简单,就是逐个调用一下 BeanDefinitionRegistryPostProcessor后置处理器。

    /**
     * Invoke the given BeanDefinitionRegistryPostProcessor beans.
     * 调用给定的 BeanDefinitionRegistryPostProcessor bean。
     */
    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection postProcessors, BeanDefinitionRegistry registry) {

        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }

invokeBeanFactoryPostProcessors()调用所有的BeanFactoryPostProcessor

逐个调用一下 BeanFactoryPostProcessor后置处理器。

    /**
     * Invoke the given BeanFactoryPostProcessor beans.
     * 调用给定的 BeanFactoryPostProcessor bean。
     */
    private static void invokeBeanFactoryPostProcessors(
            Collection postProcessors, ConfigurableListableBeanFactory beanFactory) {

        for (BeanFactoryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    }

beanFactory.getBeanNamesForType()根据类型获取bean名称

beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)会根据传入的类型获取该类型所有的bean名称。

跟进代码查看,会调用 doGetBeanNamesForType()方法进行获取。

    public String[] getBeanNamesForType(@Nullable Class type, boolean includeNonSingletons, boolean allowEagerInit) {
        // 配置没有冻结 || 类型为空 || 不允许提前初始化 则进入
        if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
            return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
        }
        Map, 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;
    }

跟进 doGetBeanNamesForType()方法,这个方法也比较长,但是逻辑也比较清晰,就是遍历了 beanDefinitionNames判断是否符合类型要求,符合则返回。

    private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
        List result = new ArrayList<>();

        // Check all bean definitions.
        // 从所有的 beanDefinitionNames 检查所有符合类型要求的 bean ,加入 result
        for (String beanName : this.beanDefinitionNames) {
            // Only consider bean as eligible if the bean name
            // is not defined as alias for some other bean.
            // 如果 bean 名称未定义为其他 bean 的别名,则该bean符合要求。
            if (!isAlias(beanName)) {
                try {
                    // 获取 beanName 的 RootBeanDefinition
                    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    // Only check bean definition if it is complete.
                    if (!mbd.isAbstract() && (allowEagerInit ||
                            (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
                                    !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                        boolean isFactoryBean = isFactoryBean(beanName, mbd);
                        BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
                        // 类型是否匹配
                        boolean matchFound = false;
                        boolean allowFactoryBeanInit = allowEagerInit || containsSingleton(beanName);
                        boolean isNonLazyDecorated = dbd != null && !mbd.isLazyInit();
                        // 主要就是调用 isTypeMatch() 方法判断类型是否匹配
                        if (!isFactoryBean) {
                            if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
                                matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                            }
                        }
                        else  {
                            if (includeNonSingletons || isNonLazyDecorated ||
                                    (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
                                matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                            }
                            if (!matchFound) {
                                // In case of FactoryBean, try to match FactoryBean instance itself next.
                                beanName = FACTORY_BEAN_PREFIX + beanName;
                                matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                            }
                        }
                        // 如果匹配则加入
                        if (matchFound) {
                            result.add(beanName);
                        }
                    }
                }
                catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
                    // 省略部分异常处理..
                }
            }
        }

        // Check manually registered singletons too.
        // 检查手动注册的单例bean
        for (String beanName : this.manualSingletonNames) {
            try {
                // In case of FactoryBean, match object created by FactoryBean.
                if (isFactoryBean(beanName)) {
                    if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
                        result.add(beanName);
                        // Match found for this bean: do not match FactoryBean itself anymore.
                        continue;
                    }
                    // In case of FactoryBean, try to match FactoryBean itself next.
                    beanName = FACTORY_BEAN_PREFIX + beanName;
                }
                // Match raw bean instance (might be raw FactoryBean).
                // 匹配则加入
                if (isTypeMatch(beanName, type)) {
                    result.add(beanName);
                }
            }
            catch (NoSuchBeanDefinitionException ex) {
                // 省略部分异常...
            }
        }

        return StringUtils.toStringArray(result);
    }

到这里 BeanFactoryPostProcessor的源码调用以及相关的逻辑分析完了,是不是比较简单。

小结

这篇文章主要是介绍了 BeanFactoryPostProcessor后置处理器的使用和底层原理。文章开头首先回顾了上一篇文章的内容,然后例子驱动分析,先用简单的例子实现了 BeanFactoryPostProcessor的使用,然后再进行了源码分析,整个文章下来思路是比较清晰的。那么看到这里,有没有解决了文章开头的两个疑问?

  • BeanFactoryPostProcessor是什么以及如何使用?
  • BeanFactoryPostProcessor在源码里的调用逻辑?

如果没有,那不怪你,可能是我写得不好。

今天是汶川地震14周年,生命无常,向遇难的同胞寄托哀思,向参与救援的同胞致敬。

如果有人看到这里,那在这里老话重提。 与君共勉,路漫漫其修远兮,吾将上下而求索。

Original: https://www.cnblogs.com/codegitz/p/16263623.html
Author: Codegitz
Title: Spring Ioc源码分析系列–Ioc容器BeanFactoryPostProcessor后置处理器分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/714247/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • jQuery triger与trigerHandler的区别

    trigger(event, [data]) 与 triggerHandler(event, [data]) 都是用于触发一个事件。 其两者的区别在于,如果触发的事件是有浏览器默认…

    技术杂谈 2023年5月31日
    089
  • Windows DIB文件操作具体解释-4.使用DIB Section

    前面讲了为了提高DIB的显示性能和效率,我们将DIB转换成DDB。可是这又遇到一个问题。假设我想操作DIB的数据的话,显然是不能使用DDB:一是由于DIB转DDB时发生了颜色转换。…

    技术杂谈 2023年5月31日
    072
  • 如何封装安全的go

    如何封装安全的go 在业务代码开发过程中,我们会有很大概率使用go语言的goroutine来开启一个新的goroutine执行另外一段业务,或者开启多个goroutine来并行执行…

    技术杂谈 2023年6月1日
    072
  • Qt error: ‘class Ui::XXXXX‘ has no member named ‘XXXXX‘

    这个原因是因为 设计界面对应的 ui_xx.h文件未更新造成的(原因:比如我们工程从一台机器复制到另一台机器,有可能造成该文件不再更新了)(在我们的main.cpp同级目录那个ui…

    技术杂谈 2023年5月31日
    0125
  • ps 创建文字模板的方法

    使用文字模板工具,注意不要使用移动工具移动选区,否则这样选区内的像素也会跟着移动,要使用选区工具移动和变换 Original: https://www.cnblogs.com/da…

    技术杂谈 2023年7月25日
    081
  • Kafka 是如何做到消息不丢或不重复的

    *消息重复。 相同的消息重复发送会造成消费者消费两次同样的消息,这同样会造成系统间数据的不一致。比如,订单支付成功后会通过消息队列给支付系统发送需要扣款的金额,如果消息发送两次一样…

    技术杂谈 2023年7月24日
    057
  • 字符串匹配之Sunday算法

    简介 Sunday算法是一种字符串匹配算法,相比于KMP算法,它比较简单易学。 在有些时候,比如字符串很长的时候,它是比KMP要高效的。 核心思想 从前往后匹配,匹配失败时关注主串…

    技术杂谈 2023年7月11日
    053
  • nmake

    http://t.zoukankan.com/liangxiaofeng-p-3247968.html Original: https://www.cnblogs.com/hshy…

    技术杂谈 2023年5月31日
    083
  • .net爬虫框架技术选型

    个人认为爬虫框架分抓取框架和分析框架 1)抓取框架 .net 市面上好的似乎不多,选择要素分两种:1.轻量型,2.重量型。 轻量型是可以定制一些特殊的功能或者插件开关形式。总体性能…

    技术杂谈 2023年7月24日
    079
  • map.GetLocationUnitFormat();

    Name=MeasurementUnit Value=Meter Name=UnitName Value=Meter Name=DisplayName Value=Meter Na…

    技术杂谈 2023年5月30日
    089
  • 基于DPDK开源项目

    功能模块 五、FastClick – 高速数据平面 FastClick – Click 模块化路由器的更快版本,具有批处理、高级多处理和改进的 Netmap 和 DPD…

    技术杂谈 2023年5月31日
    072
  • vnpy源码阅读学习(9)回到OptionMaster

    回到OptionMaster 根据我们对APP调用的代码阅读,我们基本上知道了一个APP是如何被调用,那么我们回到OptionMaster学习下这个APP的实现。 看看结构 cla…

    技术杂谈 2023年7月11日
    085
  • 基础篇——Pycharm的安装与使用初学者此篇够用

    简介 Pycharm是python编程过程中最为推荐的编辑调试软件之一,其使用简单,界面友好,也成了学习Python路上必须学会的软件之一,本篇教程简单介绍一下windows用户从…

    技术杂谈 2023年7月23日
    094
  • 【源码笔记】ThreadPoolExecutor#execute

    /** * Executes the given task sometime in the future. The task * may execute in a new thre…

    技术杂谈 2023年7月24日
    084
  • 向量距离与相似度函数

    1. 常见的距离计算方式 1.5 海明距离(Hamming Distance) 在信息论中,两个等长字符串之间的海明距离是两个字符串对应位置的不同字符的个数。假设有两个字符串分别是…

    技术杂谈 2023年7月11日
    062
  • 部署-jenkins发布项目到linux环境

    使用openSSH的方式 如果jenkins跟服务器不在同一台服务器上,这时候我们可以借助ssh的方式将打包好的jar包发送到远程服务器,然后以后台的方式运行程序。 安装publi…

    技术杂谈 2023年7月23日
    064
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球