spring学习(六)——3.2 Spring的 PostProcessor的使用实例

这是对BeanFactoryPostProcessor使用的一个简单示例。

实体

@Data
public class PostProcessorTestEntity {
    
    private int id;
    
    private String name;
    
}

这个是我们做实例时候用的统一的实体。

spring.xml结构

<?xml version="1.0" encoding="UTF-8" ?>
<beans   xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="postProcessorTest" class="com.learn.postprocessor.entity.PostProcessorTestEntity">
    <property name="id" value="1"/>
    <property name="name" value="xml"/>
</bean>
    
<bean class="com.learn.postprocessor.postprocessor.BeanFactoryPostProcessorTest"></bean>
<bean class="com.learn.postprocessor.postprocessor.BeanFactoryPostProcessorTest2"></bean>

</beans>

这是我们做示例时候用的XML结构,后续我会描述注入了什么,代码不再贴出

BeanFactoryPostProcessor基础的后置处理器拓展

在XML中我们注入实体,以及两个继承BeanFactoryPostProcessor和ordered接口的实体

实体,id为1 name为2

test中id为2、name为inClass,排序为1

test中id为5,排序为2

代码如下

public class BeanFactoryPostProcessorTest implements 
                                          BeanFactoryPostProcessor, Ordered {
    @Override public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用 BeanFactoryPostProcessorTest ...");
        System.out.println("容器中有 BeanDefinition 的个数:" + beanFactory.getBeanDefinitionCount());
        // 获取指定的 BeanDefinition
        BeanDefinition bd = beanFactory.getBeanDefinition("postProcessorTest");
        MutablePropertyValues pvs = bd.getPropertyValues();
        pvs.addPropertyValue("id",2);
        pvs.addPropertyValue("name","inClass");
    }

    @Override public int getOrder() {
        return 1;
    }
}
public class BeanFactoryPostProcessorTest2 implements 
                                          BeanFactoryPostProcessor, Ordered {
    @Override public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用 BeanFactoryPostProcessorTest2 ...");

        // 获取指定的 BeanDefinition
        BeanDefinition bd = beanFactory.getBeanDefinition("postProcessorTest");

        MutablePropertyValues pvs = bd.getPropertyValues();

        pvs.addPropertyValue("id",5);
    }

    @Override public int getOrder() {
        return 2;
    }
}

输出结果为

调用 BeanFactoryPostProcessorTest ...
容器中有 BeanDefinition 的个数:3
调用 BeanFactoryPostProcessorTest2 ...
name:inClass-- id:5

会发现实际上,

  • xml中设置的值被BeanFactoryPostProcessor给修改了
  • BeanFactoryPostProcessor的执行根据ordered的顺序进行执行的,最后执行的会覆盖前面的设置

PropertyPlaceholderConfigurer配置文件处理器扩展

创建一个实现相关接口的类,并在xml中注入他

public class CustomPropertyConfig extends PropertyPlaceholderConfigurer {

    private Resource[] locations;

    private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();

    @Override
    public void setLocations(Resource[] locations) {
        this.locations = locations;
    }

    @Override
    public void setLocalOverride(boolean localOverride) {
        this.localOverride = localOverride;
    }

    /**
     * 覆盖这个方法,根据启动参数,动态读取配置文件
     * @param props
     * @throws IOException
     */
    @Override
    protected void loadProperties(Properties props) throws IOException {
        if (locations != null) {
            // locations 里面就已经包含了那三个定义的文件
            for (Resource location : this.locations) {
                InputStream is = null;
                try {
                    String filename = location.getFilename();
                    String env = "application-" + System.getProperty("spring.profiles.active", "test") + ".properties";

                    // 找到我们需要的文件,加载
                    if (filename.contains(env)) {
                        logger.info("Loading properties file from " + location);
                        is = location.getInputStream();
                        this.propertiesPersister.load(props, is);

                    }
                } catch (IOException ex) {
                    logger.info("读取配置文件失败.....");
                    throw ex;
                } finally {
                    if (is != null) {
                        is.close();
                    }
                }
            }
        }
    }
    
    
}

xml中为其添加三个配置文件

<bean id="PropertyPlaceholderConfigurer" class="com.learn.postprocessor.placeholderconfigurer.CustomPropertyConfig">
        <property name="locations">
            <list>
                <value>classpath:config/application-dev.properties</value>
                <value>classpath:config/application-test.properties</value>
                <value>classpath:config/application-prod.properties</value>
            </list>
        </property>
    </bean>

实体类的注入

<bean id="postProcessorTest" class="com.learn.postprocessor.entity.PostProcessorTestEntity">
        <property name="id" value="1"/>
        <property name="name" value="${processor.name}"/>
    </bean>

三个配置文件中的processor.name分别为dev,test,prod。代码中默认配置为test配置文件,运行结果

entity name:test

会发现

  • 多个配置中,系统根据配置读取对应文件名内所写的数据。
  • spring会自动读取配置文件中对应的参数进行替换

PropertyOverrideConfigurer最终赋值的处理

创建一个实现此类的实现类,并加载配置文件中的数据

public class CustomPropertyConfig extends PropertyOverrideConfigurer {

    private Resource[] locations;

    private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();

    @Override
    public void setLocations(Resource[] locations) {
        this.locations = locations;
    }

    @Override
    public void setLocalOverride(boolean localOverride) {
        this.localOverride = localOverride;
    }

    /**
     * 覆盖这个方法,根据启动参数,动态读取配置文件
     * @param props
     * @throws IOException
     */
    @Override
    protected void loadProperties(Properties props) throws IOException {
        if (locations != null) {
            // locations 里面就已经包含了那三个定义的文件
            for (Resource location : this.locations) {
                InputStream is = null;
                try {
                    String filename = location.getFilename();
                    String env = "application.properties";

                    // 找到我们需要的文件,加载
                    if (filename.contains(env)) {
                        logger.info("Loading properties file from " + location);
                        is = location.getInputStream();
                        this.propertiesPersister.load(props, is);

                    }
                } catch (IOException ex) {
                    logger.info("读取配置文件失败.....");
                    throw ex;
                } finally {
                    if (is != null) {
                        is.close();
                    }
                }
            }
        }
    }
}

xml中值设置为固定值,不再使用占位符

  <bean id="postProcessorTest" class="com.learn.postprocessor.entity.PostProcessorTestEntity">
        <property name="name" value="xml"/>
    </bean>

实际运行结果

entity name:no

实际运行结果中,实现了PropertyOverrideConfigurer接口的类中,会自动的选号合适的类和属性名进行值的替换,不再依靠占位符。

项目demo保存在 https://gitee.com/daifylearn/springLearn

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值