Spring Boot源码(五):BeanFactoryPostProcessor和BeanPostProcessor

BeanFactoryPostProcessor是spring BeanFactory加载Bean后调用,

BeanPostProcessor是Bean初始化前后调用。

BeanFactoryPostProcessor

通俗地说:BeanFactoryPostProcessor是胚胎中直接基因改造,BeanPostProcessor是出生后去整容。

 

 

 上面是refresh()方法的一部分,之前还调用了

prepareBeanFactory(beanFactory);

 

 

 配置beanFactory

invokeBeanFactoryPostProcessors(beanFactory);

 

 

 

 

 

 

 这个方法去执行BeanFactoryPostProcessor下的类。包括自己定义的一些类,mybatis 整合spring就是通过这个。但我们写crud是不用这些东西的,只看一个简单的demo:

新建一个类实现BeanFactoryPostProcessor :

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("people");
        genericBeanDefinition.setBeanClass(User.class);

        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        constructorArgumentValues.addIndexedArgumentValue(0,"abc");
        genericBeanDefinition.setConstructorArgumentValues(constructorArgumentValues);
    }
}

 


实现postProcessBeanFactory()方法,在这个方法中拿到people的beanDefinition,这里用子类去接收,因为子类api更丰富,

然后修改他的beanClass为User类(注意User类没有注入Spring 容器):

public class User {
}

运行Test main方法:

public class Test {
    public static void main(String[] args) {
        //通过注解配置类初始化 spring上下文
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(MyConfig.class);
        //还有一种通过xml来初始化 spring上下文,这里就不介绍了。
        //ClassPathXmlApplicationContext
        System.out.println(annotationConfigApplicationContext.getBean("people"));
    }
}

输出结果为:

component.User@4671e53b

所以我们可以通过BeanFactoryPostProcessor修改beanDefinition。

其中还有两个属性简单说下

 

autowireMode:自动装配模型。可以设置4个值:

 

/**
* Constant that indicates no externally defined autowiring. Note that
* BeanFactoryAware etc and annotation-driven injection will still be applied.
*/
int AUTOWIRE_NO = 0;

/**
* Constant that indicates autowiring bean properties by name
* (applying to all bean property setters).
*/
int AUTOWIRE_BY_NAME = 1;

/**
* Constant that indicates autowiring bean properties by type
* (applying to all bean property setters).
*/
int AUTOWIRE_BY_TYPE = 2;

/**
* Constant that indicates autowiring the greediest constructor that
* can be satisfied (involves resolving the appropriate constructor).
*/
int AUTOWIRE_CONSTRUCTOR = 3;

默认是0,不自动装配。
如果设置为1,2。那么该类下的依赖不需要@Autowired或@Resource注解了
@Component
public class People {
    private User user;
}

对people的beanDefinition设置自动装配,则user也可以正常使用,而不会NPE。


constructorArgumentValues:
这个参数会决定bean实例化时调用的构造方法,默认是无参构造器。
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        constructorArgumentValues.addIndexedArgumentValue(0,"abc");
        genericBeanDefinition.setConstructorArgumentValues(constructorArgumentValues);

这里会调用的是一个参数是字符串的构造方法。

 

BeanPostProcessor

 BeanPostProcessor称为后置处理器,spring框架中很多技术实现了此接口。例如自动注入等,spring中使用了5个子类初始化bean。这个以后再说

 

 

 

 

 

 

 

 此方法中:

 

 

 

 

 

 这里调用的方法就是实例化前和实例化后。

使用示例:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
        return bean;
    }

}

 

posted @ 2020-02-11 17:22  SunSAS  阅读(1170)  评论(0编辑  收藏  举报