BeanFactoryPostProcessor

        通过名字我们就可以猜测这个bean的作用:BeanFactory的后置处理器。BeanFactoryPostProcessor是实现spring容器功能扩展的重要接口,我们通过它可以动态修改bean属性值,实现bean动态代理等,首先看一下接口的定义。

 
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.
* @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容器初始化之后修改BeanFactory的内容,此时所有的bean已经定义过,但是没有还初始化。此时允许重写我们修改bean的定义。
 
下面以学生、汽车为模型,简单学习一下BeanFactoryPostProcessor的使用,顺便复习一下spring中Bean的加载流程和动态代理。
 
学生类
public class Student implements InitializingBean,BeanPostProcessor {

    Car car;



    public void start(){
        System.out.println("start --->执行");
        car.run();
    }



    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet 执行");
        if(car == null){
            System.out.println("car not setting");
        }else {
            System.out.println("car installed");
        }

    }


    public Student() {
        System.out.println("Student 构造器 执行");
        if(car == null){
            System.out.println("car not setting");
        }else {
            System.out.println("car installed");
        }
    }

    @PostConstruct
    public void init(){
        System.out.println("PostConstruct 执行");
        if(car == null){
            System.out.println("car not setting");
        }else {
            System.out.println("car installed");
        }
    }

    public void setCar(Car car) {
        this.car = car;
    
}

汽车接口

public interface Car {
    void run();
}

我们将 Student 注入Spring 容器

    @Bean(initMethod = "start")
    public Student student(Car car1){
        Student student = new Student();
        student.setCar(car1);
        return student;
    }

汽车接口没有实现,这么启动肯定报错。我们可以通过动态代理实现Car接口并将它放入Spring容器中

public class SpecialBeanForCar implements BeanFactoryPostProcessor {

    String name;


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("postProcessBeanFactory running");
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) configurableListableBeanFactory;
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();

        genericBeanDefinition.setBeanClass(MyFactory.class);

        genericBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
        genericBeanDefinition.setAutowireCandidate(true);
        registry.registerBeanDefinition("car", genericBeanDefinition);
    }


    public static class MyFactory implements FactoryBean<Car>, InvocationHandler {


        @Override
        public Car getObject() throws Exception {
            System.out.println("CarFactory  to build car");
            return (Car) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Car.class}, this);
        }

        @Override
        public Class<?> getObjectType() {
            return Car.class;
        }

        @Override
        public boolean isSingleton() {
            return true;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("汽车跑起来了");
            return null;
        }
    }
}

将 SpecialBeanForCar注入Spring

    @Bean
    public SpecialBeanForCar specialBeanForCar(){
        return new SpecialBeanForCar();
    }

执行Application后打印如下

postProcessBeanFactory running
Student 构造器 执行
car not setting
PostConstruct 执行
car installed
afterPropertiesSet 执行
car installed
start --->执行
汽车跑起来了

通过结果我们可以知道Spring Bean的加载流程

 BeanFactoryPostProcessor ---> 普通Bean构造方法 ---> 设置依赖或属性 ---> @PostConstruct ---> InitializingBean ---> initMethod 

 
 
 
 

猜你喜欢

转载自www.cnblogs.com/gaoju666/p/11844640.html