BeanFactoryPostProcessor是用来处理修改bean定义信息的后置处理器,这个时候bean还没有初始化,只是定好了BeanDefinition,在BeanFactoryPostProcessor接口的postProcessBeanFactory方法中,我们可以修改bean的定义信息,例如修改属性的值,修改bean的scope为单例或者多例。
BeanPostProcessor则是bean初始化前后对bean的一些操作,意思就是说bean在调用构造之后,初始化方法前后进行一些操作。
BeanPostProcessor
public interface BeanPostProcessor {
//初始化调用方法之前调用(一般我们说来就是initMethod方法或者@PostConstruct注解方法,当然还有其他的方式实现初始化方法),是在构造方法之后执行的
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//初始化方法之后进行调用
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
进入实现BeanPostProcessor类的方法里面的bean都是已经实例化好的,可以直接用来使用,也就是参数里面的bean可以直接转成我们需要的对象,然后进行属性操作,例如你可以在这里对bean进行设置值,一般来说我们都是在用自定义注解的时候会判断这些bean的字段是否包含我们的自定义注解,当然了还有其他的一些用途,看自己怎么使用了。这里需要主要的一点是在高版本的BeanPostProcessor这个接口,都使用了default
实现了默认写法。
BeanFactoryPostProcessor
@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.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
//这个是所有的bean的定义信息定义好之后,初始化前的最后一次提供修改的操作,这里一般都是用来修改bean的定义信息或者修改bean的属性用的,这个接口没有提供默认的实现方法,它是一个void方法
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
下面写两个测试类进行测试
package com.madman.annotation.springextension;
import com.madman.annotation.entity.Blue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
*
* 【类型】: MyBeanPostProcesser
* 【作用】: 请填写此类的作用
* 【时间】:2019/1/3 17:29
* 【作者】:madman
*
*/
@Configuration
@Component
public class MyBeanFactoryPostProcesser implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//这种方法尽量不要用,这里获取Bean的时候会把对象对实例化掉,正常来说这里只是bean的定义信息
//https://www.jianshu.com/p/3d099ea43b0e
//Blue bule_01 = beanFactory.getBean("bule_01", Blue.class);
//InitializingBean
BeanDefinition bule_01 = beanFactory.getBeanDefinition("bule_01");
bule_01.getPropertyValues().add("name", "哈哈哼哼");
bule_01.setScope(BeanDefinition.SCOPE_SINGLETON);
// bule_01.setInitMethodName();
System.out.println("BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用...");
}
}
自定义一个BeanFactoryPostProcessor接口的实现类,并在里面修改了bean的scope属性,还可以修改initMethod方法,关于bean的定义信息这里都可以修改,但是这里也做一个操作的操作,就是Blue bule_01 = beanFactory.getBean("bule_01", Blue.class);
前面已经提到过BeanFactoryPostProcessor是提供给你修改的bean的定义信息的口子,也就是修改BeanDefinition
对象的属性,如果在这里getBean(""),就会把bean的初始化信息给提前了,这破坏了spring的封装特性,使用BeanFactoryPostProcessor——这种姿势不要用
MyBeanPostProcesser
自定义BeanPostProcessor
package com.madman.annotation.springextension;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
/**
*
* 【类型】: MyBeanPostProcesser
* 【作用】: 请填写此类的作用
* 【时间】:2019/1/3 17:29
* 【作者】:madman
*
*/
@Configuration
@Component
public class MyBeanPostProcesser implements BeanPostProcessor {
@Nullable
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("beanName的名字是:" + beanName + ",BeanPostProcessor的postProcessBeforeInitialization方法正在调用...");
return bean;
}
@Nullable
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("beanName的名字是:" + beanName + ",BeanPostProcessor的postProcessAfterInitialization方法正在调用...");
return bean;
}
}
这里就是简单打印一个日志。
Blue
Blue是也个entity对象,用来测试的。
package com.madman.annotation.entity;
import javax.annotation.PostConstruct;
public class Blue {
public String name;
public Integer age;
@PostConstruct
public void cc() {
System.out.println("cc方法执行了,PostConstruct()注解驱动的啦");
}
public Blue() {
System.out.println("无参数构造函数");
}
public Blue(String name, Integer age) {
System.out.println("调用有参数构造方法...");
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Blue{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
CustomBeanDefinitionRegistryPostProcessor
这是一个辅助类,用来自定义bean注册的,就是用来定义bean的,只是没有用平常的那种方式,@Bean或者xml配置。
package com.madman.annotation.springextension;
import com.madman.annotation.entity.Blue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
*
* 【类型】: CustomBeanDefinitionRegistryPostProcessor
* 【作用】: 请填写此类的作用
* 【时间】:2019/1/3 14:50
* 【作者】:madman
*
*/
@Configuration
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("自定义的Bean信息....");
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition("com.madman.annotation.entity.Blue");
beanDefinitionBuilder.addPropertyValue("name", "小鹏一号");
beanDefinitionBuilder.addPropertyValue("age", "18");
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Blue.class).getBeanDefinition();
beanDefinition.getPropertyValues().add("name", "小鹏二号");
beanDefinition.getPropertyValues().add("age", "28");
registry.registerBeanDefinition("bule_01", beanDefinitionBuilder.getBeanDefinition());
registry.registerBeanDefinition("bule_02", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
然后写一个测试方法
package com.madman.annotation.start;
import com.madman.annotation.config.Config_1;
import com.madman.annotation.entity.Blue;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Map;
public class start_1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotation = new AnnotationConfigApplicationContext(Config_1.class);
Map beansOfType = annotation.getBeansOfType(Blue.class);
for (String s : beansOfType.keySet()) {
System.out.println("名字是:" + s);
System.out.println(beansOfType.get(s).toString());
}
}
}
结果
BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用...
beanName的名字是:config_1,BeanPostProcessor的postProcessBeforeInitialization方法正在调用...
beanName的名字是:config_1,BeanPostProcessor的postProcessAfterInitialization方法正在调用...
无参数构造函数
beanName的名字是:bule_01,BeanPostProcessor的postProcessBeforeInitialization方法正在调用...
cc方法执行了,PostConstruct()注解驱动的啦
beanName的名字是:bule_01,BeanPostProcessor的postProcessAfterInitialization方法正在调用...
无参数构造函数
beanName的名字是:bule_02,BeanPostProcessor的postProcessBeforeInitialization方法正在调用...
cc方法执行了,PostConstruct()注解驱动的啦
beanName的名字是:bule_02,BeanPostProcessor的postProcessAfterInitialization方法正在调用...
名字是:bule_01
Blue{name='哈哈哼哼', age=18}
名字是:bule_02
Blue{name='小鹏二号', age=28}
根据结果来看一下顺序是否正确。
BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用…
这句话是在MyBeanFactoryPostProcesser方法里面打印出来的,说明它的执行顺序的最前面的,我们说的这个是bean初始化前的最后一次提供修改的机会。
beanName的名字是:config_1,BeanPostProcessor的postProcessBeforeInitialization方法正在调用…
beanName的名字是:config_1,BeanPostProcessor的postProcessAfterInitialization方法正在调用…
上面这两行是一个configuration配置类,这里可以忽略。
无参数构造函数
beanName的名字是:bule_01,BeanPostProcessor的postProcessBeforeInitialization方法正在调用…
cc方法执行了,PostConstruct()注解驱动的啦
beanName的名字是:bule_01,BeanPostProcessor的postProcessAfterInitialization方法正在调用…
然后这四行是bean的一些初始化操作,首先的调用了构造方法函数,然后调用了postProcessBeforeInitialization的方法,然后调用了@PostConstruct()标注的方法(也就是我们所说的initMethod方法),然后再调用了postProcessAfterInitialization的方法,这个方法的执行顺序是在初始化方法之后的。
名字是:bule_01
Blue{name='哈哈哼哼', age=18}
这个bean的打印结果不是小鹏一号
,而是哈哈哼哼
,这个哈哈哼哼
就是在postProcessBeanFactory这个方法里面获取了bule_01
然后修改了他的属性。
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//这种方法尽量不要用,这里获取Bean的时候会把对象对实例化掉,正常来说这里只是bean的定义信息
//https://www.jianshu.com/p/3d099ea43b0e
//Blue bule_01 = beanFactory.getBean("bule_01", Blue.class);
//InitializingBean
BeanDefinition bule_01 = beanFactory.getBeanDefinition("bule_01");
bule_01.getPropertyValues().add("name", "哈哈哼哼");
bule_01.setScope(BeanDefinition.SCOPE_SINGLETON);
// bule_01.setInitMethodName();
System.out.println("BeanFactoryPostProcessor的postProcessBeanFactory方法正在调用...");
}
这里就记录一下Spring的BeanFactoryPostProcessor和BeanPostProcessor如何使用。