欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring应用手册-BeanFactoryPostProcessor接口

程序员文章站 2024-03-24 16:01:28
...

戴着假发的程序员出品 抖音ID:戴着假发的程序员欢迎关注

BeanFactoryPostProcessor接口

spring应用手册(第五部分)


BeanFactoryPostProcessor是bean工厂的bean属性处理容器,说通俗一些就是可以管理我们的bean工厂内所有的beandefinition(未实例化)数据,可以随心所欲的修改属性。

先看看源码:

package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
/**
 * Allows for custom modification of an application context's bean definitions,
 * adapting the bean property values of the context's underlying bean factory.
 */
@FunctionalInterface
public interface BeanFactoryPostProcessor {
   /**
    * 处理方法(钩子方法)
    * @param beanFactory 当前的工厂对象,我们可以通过这个工厂对象获取容器中多有的BeanDefinition信息
    */
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

我们发现这个接口中只有一个方法,传递了参数ConfigurableListableBeanFactory对象,代码中我们也解释了这个对象是什么。 问题是整个方法什么时候执行呢?

我们来看看springBean的加载流程图:
Spring应用手册-BeanFactoryPostProcessor接口
从图中我们可以看出来,spring 会加载我们编译好的Class文件,并且生成对应的BeanDefinition对象存储在缓存中,然后会根据这些BeanDefinition对象来创建对应的springBean,BeanFactoryPostProcessor就会在实例化之前执行。所以我们可以在实例化之前对bean的任何属性进行调整。

我们看一个案例: 我们在spring中注册Coder类,但是我们在实例化之前将Coder的类修改为Manager类,那么spring创建出来的coder对象应该就是Manager类的实例。 看代码:

准备两个Bean:

/**
 * @author 戴着假发的程序员
 * @company http://www.boxuewa.com
 * @description
 */
public class Coder{
    //构造方法
    public Coder(){
        System.out.println("实例化Coder对象");
    }
}
/**
 * @author 戴着假发的程序员
 * @company http://www.boxuewa.com
 * @description
 */
public class Manager {
    public Manager(){
        System.out.println("实例化Manager对象");
    }
}

自己定义一个BeanFactoryPostProcessor的实现类,在其中修改coder的class。

/**
 * @author 戴着假发的程序员
 * @company http://www.boxuewa.com
 * @description
 */
public class DkBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //获取coder的BeanDefinition对象
        BeanDefinition coder = beanFactory.getBeanDefinition("coder");
        //修改其class
        coder.setBeanClassName(Manager.class.getName());
    }
}

配置,在配置文件中配置我们的DkBeanFactoryPostProcessor,以及coder。注意不要配置Manager。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 配置我们的DkBeanFactoryPostProcessor -->
    <!-- 这里注意,我们只要将这个Bean交给spring即可,不需要id -->
    <bean class="com.igeek.dk.demo10.beanfactorypostprocessor.DkBeanFactoryPostProcessor"/>
    <!-- 正常配置colder -->
    <bean id="coder" class="com.st.dk.demo10.beans.Coder"/>
</beans>

测试,我们从容器中按照id取出coder,看看取出的对象是谁的实例:

 @Test
public void testBeanFactoryPostProcessor(){
    ApplicationContext ac =
            new ClassPathXmlApplicationContext("applicationContext-demo10.xml");
    Object coder = ac.getBean("coder");
    System.out.println("是否是Coder的实例:"+(coder instanceof Coder));
    System.out.println("是否是Manager的实例:"+(coder instanceof Manager));
}

结果:
Spring应用手册-BeanFactoryPostProcessor接口
我们会发现spring实例化的就是Manager对的实例,虽然我们配置的是Coder类型,但是实例化之前被我们使用BeanFactoryPostProcessor修改了类型。