【问题标题】:BeanFactoryPostProcessor and BeanPostProcessor in lifecycle events生命周期事件中的 BeanFactoryPostProcessor 和 BeanPostProcessor
【发布时间】:2015-08-07 22:47:21
【问题描述】:

我试图了解BeanFactoryPostProcessorBeanPostProcessor 之间的区别。

我知道BeanFactoryPostProcessor 对 bean 定义进行操作,即在创建 bean 实例之前它被执行,BeanPostProcessor 在 bean 被实例化并调用生命周期事件之后被执行。

这是否意味着 BeanFactoryPostProcessor 不是 Spring 生命周期事件的一部分,因为它在实例化之前被调用,而 BeanPostProcessor 是 Spring 生命周期事件的一部分?请验证我的理解是否正确。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    BeanFactoryPostProcessor 是一个接口,实现它的 bean 实际上是经历 Spring 生命周期的 bean(下面的示例),但这些 bean 不参与其他声明的 bean 的生命周期。

    public class CustomBeanFactory implements BeanFactoryPostProcessor {
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            for (String beanName : beanFactory.getBeanDefinitionNames()) {
    
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
    
                // Manipulate the beanDefiniton or whatever you need to do
    
            }
        }
    }
    

    BeanFactoryPostProcessorBeanPostProcessor的区别:

    1. 当所有 bean 定义都已加载但还没有 bean 被实例化时,将调用实现 BeanFactoryPostProcessor 的 bean。这允许覆盖或添加属性,甚至是急切初始化的 bean。这将让您可以访问您在 XML 中定义或已注释(通过组件扫描进行扫描)的所有 bean。
    2. 实现 BeanPostProcessor 的 bean 对 bean(或对象)实例进行操作,这意味着当 Spring IoC 容器实例化 bean 实例时,BeanPostProcessor 接口会完成它们的工作。
    3. BeanFactoryPostProcessor 实现在 Spring 上下文启动期间在所有 bean 定义都将被加载后被“调用”,而 BeanPostProcessor 在 Spring IoC 容器实例化 bean 时被“调用”(即在所有单例和按需启动期间对于原型之一)

    【讨论】:

    • 当BeanFactoryPostProcessor的回调方法被调用时,它如何覆盖bean中尚未创建的属性?这是否意味着它将使用的占位符替换为为 bean 加载的字节码中的实际值?
    • @SumitDesai 由于 BeanFactoryPostProcessor 仅适用于 spring bean 的定义而不适用于它们的实例,因此在这种情况下覆盖属性对于针对覆盖 bean 属性的系统管理员的自定义配置文件很有用在应用程序上下文中配置(如文档 BeanFactoryPostProcessor 中所述)。
    • 我理解允许系统管理员允许覆盖属性的目的。但是,我的问题是 BeanFactoryPostProcessor 是如何做到的?它是否使用反射修改 bean 定义?
    • 可以访问postProcessBeanFactory方法中的ConfigurableListableBeanFactory beanFactory,你可以通过beanFactory.getBeanDefinition("yourBeanName").getPropertyValues()访问bean定义及其属性,然后你可以添加或修改它们。
    • beanFactory.getBeanDefinition("yourBeanName") 提供对 bean 定义而不是 bean 实例的访问权限,因此如果您仅与 bean 的定义(bean 的名称、要实例化的类、要注入的属性、依赖项...)不会创建任何bean。但是,如果您与 bean 的实例进行交互,它将立即创建一个,而无需经过正常的 bean 创建过程。
    【解决方案2】:

    BeanFactoryPostProcessor 在 bean Object 实例化之前执行(即在 Applicationcontext 容器初始化时)

    BeanPostprocessor在bean对象创建后执行,因为它可以在init()之前和init()之后执行。

    【讨论】:

      【解决方案3】:

      这是一个可能有助于理解 Spring bean 初始化生命周期的流程图。

      如我们所见,BeanFactoryPostProcessor 的实现在任何 spring bean 实例化之前执行,与 BeanPostprocessor 不同,后者只有在 bean 实例化时才会执行实现的方法。

      源图片来自 Spring 5 Design Patterns Book。

      我从书中挑选解释:

      从所有样式的配置中加载 bean 定义后, BeanFactoryPostProcessor进入图片修改 定义一些bean,然后容器实例化 豆子。最后,BeanPostProcessor 在 bean 上工作,它可以 修改和更改 bean 对象。这是初始化阶段。

      【讨论】:

        【解决方案4】:

        Bean Factory 后处理器 (BFPP):

        当我们想要覆盖 XML/注解时使用,因为 Spring 读取 XML/注解来创建 bean。如果您想在创建期间(在运行时)为 Spring 提供不同的配置,那么您需要使用 BFPP。创建内部依赖图是一次性的过程。

        Bean 后处理器 (BPP):

        上述步骤只发生了一次。这就像创建 bean 的“菜单”。创建 bean 后,如果要更改 bean 属性,则不能对 XML/注解进行任何更改。相反,您可以在创建后使用 BPP 更改 bean 配置。 BPP 有 2 个执行区,一个在@postconstruct 之前,一个在@postconstruct 之后。

        实时示例:

        您想从 Zomato 在线下订单。在线订购时,您向餐厅提供一份食物清单(XML/注释)。但是,就在餐厅开始制作食物之前,您打电话给他们并要求他们换菜(BFPP)。现在食物已准备好交付并且您已经收到(创建了 Bean)。但是你想做一些修改(比如盐或冷粉),你可以在品尝食物之前这样做(因为你知道餐馆从来没有放足够的盐),甚至在品尝食物之后(这是@postconstruct之前和之后) .一旦味道好,食物就准备好了(豆子可以使用了)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多