博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Spring4揭秘 BeanFactory】修改BeanFactory-BeanFactoryPostProcessor
阅读量:4290 次
发布时间:2019-05-27

本文共 5772 字,大约阅读时间需要 19 分钟。

一、BeanFactoryPostProcessor

当spring初始化好BenaDefinnitionMap之后,提供了一个接口BeanFactoryPostProcessor,允许我们开发者自定义的去修改BeanFactory中的内容,这也是符合“spring”的开闭原则

public interface BeanFactoryPostProcessor {
/** * 这里提供了修改beanFacotry的机会 */ void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}

BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor ,提供了更强大的功能。

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/** * 这个接口继承了postprocessor 并且将beanFactory转成了registry能够访问并修改BeanDefinition。 */ void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;}

二、自定义BeanFactoryPostProcessor

实现BeanFactoryPostProcessor接口即可

public class MyFactoryProcessor implements BeanFactoryPostProcessor {
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //这里可以调用ConfigurableListableBeanFactory方法对它处理 //... System.out.println("postProcessBeanFactory处理中...."); }}

手动调用BeanFactoryPostProcessor

public class Tester {    public static void main(String[] args) throws Exception {        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();        new MyFactoryProcessor().postProcessBeanFactory(factory);    }}==============输出:============postProcessBeanFactory处理中....

三、Spring常用BeanFactoryPostProcessor

spring也提供了不少BeanFactoryPostProcessor的实现,最常用的几个:PropertySourcesPlaceholderConfigurer 、 CustomerEditorConfigurer、 PropertyOverrideConfigurer等。

3.1 占位符处理器

这里写图片描述

【PropertyPlaceholderConfigurer】可以从属性文件、属性类获取属性
【PreferencesPlaceholderConfigurer】对属性来源具有优先级顺序
【PropertySourcesPlaceholderConfigurer 】提供了比PropertyPlaceholderConfigurer更强大的功能,可以从属性文件、属性类、环境、PropertySources等获取属性(Spring3.1以后推荐使用这个类)
【PropertyOverrideConfigurer】可以读取带有bean id的属性直接向bean注入属性,而不需要配置

PropertySourcesPlaceholderConfigurer

使用方法:

public class Tester {    public static void main(String[] args) throws Exception {        //创建一个BeanFactory,并注册一个bean,bean的类名用占位符表示        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();        RootBeanDefinition beanDefinition = new RootBeanDefinition("${beanName}");//占位符        beanDefinition.setScope("${scop}");//占位符        factory.registerBeanDefinition("myBean", beanDefinition);        //创建一个PropertySourcesPlaceholderConfigurer,        //并加入含有占位符字符串对应的 MutablePropertySources        PropertySourcesPlaceholderConfigurer configurer                 = new PropertySourcesPlaceholderConfigurer();        Map
map = new HashMap<>(); map.put("beanName", "Tester");//占位符对应 map.put("scop", RootBeanDefinition.SCOPE_PROTOTYPE);//占位符对应“prototype” MutablePropertySources sources = new MutablePropertySources(); sources.addLast(new MapPropertySource("abc", map)); configurer.setPropertySources(sources); //对 BeanFactory增强,会替换掉占位符 configurer.postProcessBeanFactory(factory); //获取这个bean System.out.println(factory.getBeanDefinition("myBean")); System.out.println(factory.getBean("myBean")); } @Override public String toString() { return "A bean"; }}

3.2 CustomerEditorConfigurer

java是强类型的一种语言:int,String,String[],Person等等等等。

而我们配置的xml,里面都是字面量,也就是说,spring拿到的原始数据全部是字符串。
那么,spring是怎么把字符串转成各种各样的类型呢? 用 CustomEditorConfigurer,
Spring内部通过JavaBean的PropertyEditor来帮助进行String类型到其他类型的转换工作。只要为每种对象类型提供一个PropertyEditor,就可以根据该对象类型取得与其相对应的PropertyEditor来做具体的类型转换。Spring容器内部在做具体的类型转换的时候,会采用JavaBean框架内默认的PropertyEditor搜寻逻辑。

3.3 ConfigurationClassPostProcessor

ConfigurationClassPostProcessor是一个BeanFactory和BeanDefinitionRegistry处理器,BeanDefinitionRegistry处理方法能处理@Configuration等注解。

通过查看源码,ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(..)内部使用ConfigurationClassParser类来处理@Configuration,@Import,@ImportResource和类内部的@Bean
如果@Import包含的Bean为ImportSelector类型。还会调用ImportSelector#selectImports()生成相应的Bean。
【ConfigurationClassPostProcessor基本使用】

class User{   //示例类}@Configuration@Import({User.class})public class ConfigTest {    @Bean    Date date() {        return new Date();    }    public static void main(String[] args) {        ConfigurationClassPostProcessor postProcessor = new ConfigurationClassPostProcessor();        SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();        registry.registerBeanDefinition("test", new RootBeanDefinition(ConfigTest.class));        //处理BeanDefinitionRegistry        postProcessor.postProcessBeanDefinitionRegistry(registry);        //输出结果        System.out.println(registry.getBeanDefinition("test"));//可以输出        System.out.println(registry.getBeanDefinition("date"));//可以输出        System.out.println(registry.getBeanDefinition("User"));//可以输出    }}

【ConfigurationClassPostProcessor配合@Import/ImportSelector使用】

class User{
//示例类}class MySelector implements ImportSelector{
//自定义一个ImportSelector实现类 @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //会生成两个Bean(java.util.Date和User) return new String[]{
"java.util.Date","User"}; }}@Configuration@Import({MySelector.class})public class ConfigTest {
public static void main(String[] args) { ConfigurationClassPostProcessor postProcessor = new ConfigurationClassPostProcessor(); SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); registry.registerBeanDefinition("test", new RootBeanDefinition(ConfigTest.class)); postProcessor.postProcessBeanDefinitionRegistry(registry); System.out.println(registry.getBeanDefinition("test"));// System.out.println(registry.getBeanDefinition("User"));//可以输出 System.out.println(registry.getBeanDefinition("java.util.Date"));//可以输出 }}
你可能感兴趣的文章
让数据库不再成为业务发展瓶颈——分布式数据库架构设计
查看>>
java多线程有哪些实际的应用场景?
查看>>
分布式集群Session共享~多个tomcat7+redis的session共享实现
查看>>
实例|如何从两个List中筛选出相同的值
查看>>
搭建ECS云服务器(5)设置nginx+fastdfs+tomcat+redis开启自启动
查看>>
SSO单点登录的发展由来以及实现原理
查看>>
阿里巴巴,排行前10的开源项目,第一不是Dubbo!
查看>>
手把手教你新装的linux之后的必要配置(9)
查看>>
Java互联网架构-Spring分布式事务
查看>>
持久化框架:轻量级的关系型数据库中间件 Sharding-JDBC
查看>>
Java中如何实现分页功能
查看>>
简述架构演变过程中对session存储以及权限校验的不同的解决方案
查看>>
Spring Cloud是什么,和Dubbo对比如何?
查看>>
【Lucene】Apache Lucene全文检索引擎架构之入门实战
查看>>
【Lucene】Apache Lucene全文检索引擎架构之构建索引
查看>>
Apache Lucene全文检索引擎架构之搜索功能
查看>>
【Lucene】Apache Lucene全文检索引擎架构之中文分词和高亮显示
查看>>
搜索服务Solr集群搭建 使用ZooKeeper作为代理层
查看>>
Java互联网架构-MyCat介绍与基本使用
查看>>
网易云基础服务郭忆:谈谈数据库的跨机房容灾
查看>>