SpringBoot/Spring扩展点系列之叱咤风云BeanFactoryPostProcessor - 第428篇

导读

       当我们有场景需要对类的属性进行修改或者对于加密的数据进行解密的时候,这时候BeanFactoryPostProcessor接口的postProcessBeanFactory就可以派上用场了。

(1)✅《SpringBoot/Spring扩展点之初出茅庐ApplicationContextInitializer

(2)✅《SpringBoot/Spring扩展点之略有小成BeanDefinitionRegistryPostProcessor

(3)《SpringBoot/Spring扩展点系列之叱咤风云BeanFactoryPostProcessor》

       这一节我们就来看看:

《SpringBoot/Spring扩展点系列之叱咤风云BeanFactoryPostProcessor》

一、BeanFactoryPostProcessor基本概念

1.1是什么?

       BeanFactoryPostProcessor就是BeanFactory的后处理类。

Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。

注意:BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息。

1.2 使用场景

(1)对敏感信息的解密处理

       数据库的连接配置中,用户名和密码都是明文配置的,这就存在泄漏风险,还有redis的连接配置、shiro的加密算法、rabbitmq的连接配置等等,凡是涉及到敏感信息的,都需要进行加密处理,信息安全非常重要。

       配置的时候以密文配置,在真正用到之前在spring容器中进行解密,然后用解密后的信息进行真正的操作。

(2)Spring中占位符的处理

1.3 其它说明

BeanFactoryPostProcessor可以在Bean实例化之前修改Bean的属性,但不适合在BeanFactoryPostProcessor中做Bean的实例化,这样会导致一些意想不到的副作用,就是不要把Spring玩坏了,若需要做Bean的实例化可以使用BeanPostProcessor

(1)BeanFactoryPostProcessor允许使用者修改容器中的bean definitions。

(2)BeanFactoryPostProcessor可以与bean definitions打交道,但是千万不要进行bean实例化。

二、BeanFactoryPostProcessor扩展实现方式

方式一:使用@Configuration+ @Bean 方式初始化

方式二:使用@ComponentScan+ @Component方式初始化

接下来通过方式二来看下。

2.1 构建一个应用

       这里使用了上一节构建的应用,你可以接着或者重新构建一个新的Sprin Boot项目。

2.2 定义一个User

       先构建一个User:

package com.kfit.demo.bean;public class User {    private String userName;    private int age;    public User(String userName,int age){        this.userName = userName;        this.age = age;    }    public String getUserName() {        return userName;    }    public void setUserName(String userName) {        this.userName = userName;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}

2.3 注入User

       使用@Configuration注入User:

package com.kfit.config;import com.kfit.demo.bean.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class UserConfig {    @Bean(name = "user")    public User user(){        System.out.println("Configuration.user");        return new User("WuQian",18);    }}





       如果此时启动应用,获取user bean的话,打印userName值是WuQian。

2.3自定义BeanFactoryPostProcessor

       自定义一个BeanFactoryPostProcessor,然后修改user的属性值:

package com.kfit.config;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.stereotype.Component;/** * 扩展点BeanFactoryPostProcessor * * @author 悟纤「公众号SpringBoot」 * @date 2022-05-24 * @slogan 大道至简 悟在天成 */@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {        System.out.println("MyBeanFactoryPostProcessor.postProcessBeanFactory-->start");        BeanDefinition bd = beanFactory.getBeanDefinition("user");        //开始修改属性的值        bd.getPropertyValues().add("userName","悟纤");        System.out.println("MyBeanFactoryPostProcessor.postProcessBeanFactory-->end");    }}

       自定义一个MyBeanFactoryPostProcessor实现BeanFactoryPostProcessor接口,重写postProcessBeanFactory()方法来实现对User Bean定义的修改

       可以在任意一个service类使用User,

package com.kfit.demo.service;import com.kfit.demo.bean.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;/** * * * @author 悟纤「公众号SpringBoot」 * @date 2022-05-16 * @slogan 大道至简 悟在天成 */@Servicepublic class DemoService {    @Value("${test.name}")    private String name;    @Autowired    private User user;    public DemoService(){        System.out.println("DemoService.DemoService()");    }    @PostConstruct    public void  init(){        System.out.println("DemoService.init ,name ="+name);        System.out.println("DemoService.init -> " +user.getUserName());    }}

       启动应用看下结果:

       从这里的控制台的信息的打印也可以看出前面的几个扩展点确实在BeanFactoryPostProcessor之前执行的。

       另外就是user对象的属性值确实是被替换了。



购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287