浅析Spring IoC源码(六)BeanFactoryPostProcessor

上两节,我们仔细地描述了BeanPostProcessor这个接口的作用和存在的意义,并举了2个实例说明了它的作用,这一节我们接假模假样的庖丁解牛一发,这次我们一起看下BeanFactoryPostProcessor这个接口,乍一看,这个接口与BeanPostProcessor就相差了一个Factory,那么这个接口的作用是什么呢,老规矩,我们还是打开源码,也许能看出一点蛛丝马迹:

红色区域标注出:允许自定义去修改应用上下文中的beanDefinnition,来适配底层上下文bean的属性值

这句话的意思其实很好理解,当spring初始化好benaDefinnitionMap之后,提供了一个借口允许我们开发者自定义的去修改beanDefinition中的内容,这也是符合“spring”的开闭原则



我们来对比一下,BeanFactoryPostProcessor与BeanPostProcessor的区别,BeanPostProcessor官方注释是:

工厂钩子允许自定义修改新的bean的实例,区别就是BeanFactoryPostProcessor修改的是BeanFactory中的BeanDefinnition,BeanPostProcessor修改的是当我们初始化Bean的时候,“临时”修改bean的属性


一个是从根本上去修改,一个是临时修改,举例来说:BeanDefinnition是一个名片,当你发现这个名片有问题的时候,你会告诉做这个名片的factory,帮我重新做,这就是BeanFactoryPostProcessor的功能,而BeanPostProcessor只是用笔临时修改了一下属性而已



我们再来看看BeanFactoryPostProcessor里面定义的方法,不看之前,我们可以思考,BeanPostProcessor自定义修改的是Bean,所以我们BeanPostProcessor入参有Bean,那么,我们BeanFactoryPostProcessor修改的BeanDifinition而我们BeanDefinnition在BeanFactory,所以要么传入BeanDefinnitionMap要么传入BeanFactory:

果然传入的就是beanFactory


照例,我们依旧给出代码,代码背景依旧是修改“老师抽烟”这个问题

Teacher.Java

[java]  view plain  copy
  1. <span style="color:#000000;">package org.study.spring.beanfactorypostprocessor;  
  2.   
  3. public class Teacher {  
  4.       
  5.     /** 
  6.      * 老师的姓名 
  7.      */  
  8.     private String name;  
  9.       
  10.     /** 
  11.      * 年龄 
  12.      */  
  13.     private int age;  
  14.       
  15.     /** 
  16.      * 是否抽烟 
  17.      */  
  18.     private boolean smoking;  
  19.       
  20.     /** 
  21.      * 老师教授的课程 
  22.      */  
  23.     private String language;  
  24.       
  25.       
  26.       
  27.     public Teacher() {  
  28.           
  29.     }  
  30.        
  31.   
  32.     public String getName() {  
  33.         return name;  
  34.     }  
  35.   
  36.     public void setName(String name) {  
  37.         this.name = name;  
  38.     }  
  39.   
  40.     public int getAge() {  
  41.         return age;  
  42.     }  
  43.   
  44.     public void setAge(int age) {  
  45.         this.age = age;  
  46.     }  
  47.   
  48.     public boolean isSmoking() {  
  49.         return smoking;  
  50.     }  
  51.   
  52.     public void setSmoking(boolean smoking) {  
  53.         this.smoking = smoking;  
  54.     }  
  55.   
  56.   
  57.     public String getLanguage() {  
  58.         return language;  
  59.     }  
  60.   
  61.     public void setLanguage(String language) {  
  62.         this.language = language;  
  63.     }  
  64.       
  65.     public void teach(){  
  66.         System.out.println("I am :"+name+" and I will teach you :"+language + " and I "+(smoking?"will":"will not")+" smoking");  
  67.     }  
  68.       
  69.   
  70. }</span>  
ChangeTeacherBeanFactoryPostProcessor.java

[java]  view plain  copy
  1. package org.study.spring.beanfactorypostprocessor;  
  2.   
  3. import org.springframework.beans.BeansException;  
  4. import org.springframework.beans.MutablePropertyValues;  
  5. import org.springframework.beans.factory.config.BeanDefinition;  
  6. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;  
  7. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
  8.   
  9. public class ChangeTeacherBeanFactoryPostProcessor implements BeanFactoryPostProcessor{  
  10.   
  11.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {  
  12.           
  13.         BeanDefinition beanDefinition = beanFactory.getBeanDefinition("teacher");  
  14.         MutablePropertyValues mutablePropertyValues = beanDefinition.getPropertyValues();  
  15.         if(mutablePropertyValues.contains("smoking")){  
  16.             mutablePropertyValues.add("smoking"false);  
  17.         }  
  18.           
  19.     }  
  20.   
  21. }  
bean-post-processor-teacher.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
  7.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  
  8.         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd  
  9.         http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd  
  10.         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">  
  11.    
  12.         <bean id="teacher" class="org.study.spring.beanpostprocessor.demo.Teacher">  
  13.           <property name="name" value="孔浩"/>  
  14.           <property name="age" value="32"/>  
  15.           <property name="smoking" value="true"/>  
  16.           <property name="language" value="java"/>  
  17.         </bean>  
  18.           
  19.         <bean id="changeTeacher" class="org.study.spring.beanpostprocessor.demo.ChangeTeacherSmokingBeanPostProcessor"/>  
  20.             
  21.   
  22. </beans>  
ChangeTeacherBeanFactoryPostProcessorTest.java

[java]  view plain  copy
  1. package org.study.spring.beanfactorypostprocessor;  
  2.   
  3. import org.junit.Test;  
  4. import org.springframework.context.ApplicationContext;  
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  6.   
  7. public class ChangeTeacherBeanFactoryPostProcessorTest{  
  8.       
  9.       
  10.     @Test  
  11.     public void test2() throws Exception{  
  12.          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beanfactory-post-processor-teacher.xml");  
  13.          Teacher teacher = applicationContext.getBean("teacher",Teacher.class);  
  14.          teacher.teach();  
  15.            
  16.     }  
  17.   
  18. }  
运行结果:


貌似这节结束了,其实还没有,我们再看看看BeanFactoryPostProcessor这个在Spring中的用到的地方吧

还记得我们上节利用BeanPostProcessor去切换生成环境jdbc.properties的代码吧,我们这边就简单的分析一下Spring官方给出的代码吧

打开你身边的项目,随便找一个spring与mybatis或者hibernate整合的xml配置文件,例如spring-mybatis.xml

中间有一段:

我们看看spring是如何利用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer去替换${}等等之类的值的,我们打开继承图



我们发现PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor接口,我们在PropertyResourceConfigurer.java中找到BeanFactoryPostProcessor接口中postProcessBeanFactory方法的具体实现

,我这边就不具体与大家分享了,有兴趣的大家可以自己去debug一下~

就是这个方法,大家自己有兴趣看下吧~


下一节:与大家一起理解BeanFactory与FactoryBean的这2个面试常常问到的问题~


END~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值