BeanPostProcessor后置处理器可以在Bean初始化前后做一些事情,注意这里是bean的初始化,不是实例化,BeanPostProcessor是一个接口,里面提供了两个方法,分别为postProcessBeforeInitialization(初始化之前)和postProcessAfterInitialization(初始化之后),在方法入参中有两个参数,一个bean对象,一个bean名称,这里也可以看出,在初始化之前应该已经完成了bean的实例化,这里把实例化的bean对象作为参数传了进来:- public interface BeanPostProcessor {
- @Nullable
- default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- @Nullable
- default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
- }
复制代码 来看一个例子,首先创建一个Bean,使用@Component将该bean交给Spring容器管理:- // 使用@Component将该bean交给Spring管理
- @Component
- public class User {
- private String name;
- public User() {
- System.out.println("调用User构造函数");
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
复制代码 接下来创建一个自定义的Bean后置处理器,实现BeanPostProcessor接口,并实现postProcessBeforeInitialization和postProcessAfterInitialization方法,使用@Component将该bean交给Spring管理,Spring会获取后置处理器,在bean进行初始化前后触发对应的方法。
为了打印便于观察输出结果,这里对Bean类型进行了判断,只有User类型才打印日志:- // 使用@Component将该bean交给Spring管理
- @Component
- public class MyBeanPostProcessor implements BeanPostProcessor {
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- // 只处理User类型
- if (bean instanceof User) {
- System.out.println("【后置处理器】postProcessBeforeInitialization");
- }
- return bean;
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- // 只处理User类型
- if (bean instanceof User) {
- System.out.println("【后置处理器】postProcessBeforeInitialization");
- }
- return bean;
- }
- }
复制代码 进行测试,从容器中获取user对象:- // 注意这里要扫描包
- @ComponentScan(basePackages = {"com.example.demo"})
- @SpringBootTest
- class SpringbootWebApplicationTests {
- @Test
- void contextLoads() {
- AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringbootWebApplicationTests.class);
- User User = (User) applicationContext.getBean("user", User.class);
- System.out.println("userName:" + User.getName());
- }
- }
复制代码 打印结果:- 调用User构造函数
- 【后置处理器】postProcessBeforeInitialization
- 【后置处理器】postProcessBeforeInitialization
- userName:null
复制代码 从结果中也可以看出,后置处理器中的方法,是在bean已经完成了实例化之后触发的,所以通过后置处理器可以对bean的属性进行设置,甚至可以更改bean对象本身。
比如在postProcessBeforeInitialization方法中,为User设置名称:- // 使用@Component将该bean交给Spring管理
- @Component
- public class MyBeanPostProcessor implements BeanPostProcessor {
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- // 只处理User类型
- if (bean instanceof User) {
- User user = (User) bean;
- user.setName("zhangsm");
- System.out.println("【后置处理器】postProcessBeforeInitialization");
- return user;
- }
- return bean;
- }
- }
复制代码 再次运行将会输出以下内容:- 调用User构造函数
- 【后置处理器】postProcessBeforeInitialization
- 【后置处理器】postProcessBeforeInitialization
- userName:zhangsm
复制代码 再看一下对bean本身进行更改的例子,再新增一个AdminUser类,继承User,注意AdminUser没有使用注解,也就是没有交给Spring进行管理,之后我们通过手动实例化的方式,将Spring容器中User改成AdminUser类型:- public class AdminUser extends User {
- }
复制代码 修改MyBeanPostProcessor中的postProcessAfterInitialization方法,方法的返回值是Object类型,在这里更改bean对象并返回进行替换:- @Component
- public class MyBeanPostProcessor implements BeanPostProcessor {
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- if (bean instanceof User) {
- // 这里手动创建了一个AdminUser并返回
- AdminUser user = new AdminUser();
- user.setName("administator");
- System.out.println("【后置处理器】postProcessBeforeInitialization");
- return user;
- }
- return bean;
- }
- }
复制代码 修改测试类,这次把class信息也打印:- @ComponentScan(basePackages = {"com.example.demo"})
- @SpringBootTest
- class SpringbootWebApplicationTests {
- @Test
- void contextLoads() {
- AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringbootWebApplicationTests.class);
- User User = (User) applicationContext.getBean("user", User.class);
- System.out.println("userClass:" + User.getClass());
- System.out.println("userName:" + User.getName());
- }
- }
复制代码 运行结果,可以看到拿到的bean已经是更改后的AdminUser- 调用User构造函数 // 这里是User实例化时输出的
- 【后置处理器】postProcessBeforeInitialization
- 调用User构造函数 // 这里是AdminUser实例化时输出的
- 【后置处理器】postProcessBeforeInitialization
- userClass:class com.example.demo.model.AdminUser
- userName:administator
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |