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

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

实体

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

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

spring.xml结构




    
    

    



这是我们做示例时候用的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中为其添加三个配置文件


        
            
                classpath:config/application-dev.properties
                classpath:config/application-test.properties
                classpath:config/application-prod.properties
            
        
    

实体类的注入


        
        
    

三个配置文件中的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中值设置为固定值,不再使用占位符

  
        
    

实际运行结果

entity name:no

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

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

 

 

 

你可能感兴趣的:(#,Spring源码,源码)