Spring容器提供了一个接口InitializingBean,实现这个接口的bean只要重写afterPropertiesSet()或者在XML中添加init-method属性,就可以在Bean初始化前后执行特定行为。
InitializingBean是针对单个Bean起作用的,Spring还提供了另外一个接口叫BeanPostProcessor,这个接口是针对容器中所有Bean起作用的。
只要定义个普通的Bean实现这个接口,并实现postProcessBeforeInitialization()和postProcessAfterInitialization()两个方法,容器中所有的Bean都会受影响。
下面是一个实现了BeanPostProcessor的普通bean类,
1 package spi; 2 3 import org.springframework.beans.BeansException; 4 import org.springframework.beans.factory.config.BeanPostProcessor; 5 6 public class MyBeanPostProcessor implements BeanPostProcessor { 7 8 @Override 9 public Object postProcessBeforeInitialization(Object bean, String beanName) 10 throws BeansException { 11 System.out.println("Bean后处理器在初始化之前对 "+beanName+" 进行增强处理..."); 12 return bean; 13 } 14 15 @Override 16 public Object postProcessAfterInitialization(Object bean, String beanName) 17 throws BeansException { 18 System.out.println("Bean后处理器在初始化之后对 "+beanName+" 进行增强处理..."); 19 if (bean instanceof Chinese) { 20 System.out.println("Bean后处理器将Chinese.beanName修改为‘Java编程‘."); 21 Chinese c = (Chinese)bean; 22 c.setBeanName("Java编程"); 23 } 24 return bean; 25 } 26 27 }
特意让这个bean修改chinese这个bean的属性,下面是chinese Bean的代码,
1 package spi; 2 3 import org.springframework.beans.factory.BeanNameAware; 4 import org.springframework.beans.factory.InitializingBean; 5 6 public class Chinese implements Person, InitializingBean { 7 private Son son; 8 private String beanName; 9 10 public void setBeanName(String beanName) { 11 System.out.println(beanName+":Spring正在执行setBeanName()方法注入依赖关系..."); 12 this.beanName = beanName; 13 14 } 15 public void info(){ 16 System.out.println("我在XML中的id名称为:"+beanName); 17 } 18 public int age; 19 private Axe axe; 20 public int getAge() { 21 return age; 22 } 23 public void setAge(int age) { 24 this.age = age; 25 } 26 public Axe getAxe() { 27 return axe; 28 } 29 public void setAxe(Axe axe) { 30 this.axe = axe; 31 } 32 public Chinese() { 33 System.out.println("Spring正在执行默认构造函数构造Chinese实例..."); 34 } 35 public Chinese(Axe axe) { 36 this.axe = axe; 37 } 38 public void useAxe() { 39 System.out.println("我打算去砍点柴火"); 40 System.out.println("修改beanName="+beanName+","+axe.chop()); 41 } 42 public void close() { 43 System.out.println("正在执行销毁前的方法 close ..."); 44 } 45 public Son getSon() { 46 return son; 47 } 48 public void setSon(Son son) { 49 this.son = son; 50 } 51 public void init() { 52 System.out.println("正在执行初始化方法init..."); 53 } 54 @Override 55 public void afterPropertiesSet() throws Exception { 56 // TODO Auto-generated method stub 57 System.out.println("正在执行初始化方法afterPropertiesSet..."); 58 } 59 60 }
Chinese Bean实现了InitializingBean接口,添加了init()(需要XML配置)方法和afterPropertiesSet()方法,那么它在初始化前后会被插入特定行为,行为由这两个方法决定。 同时,由于容器中存在实现了BeanPostProcessor的Bean,那么所有Bean包括chinese,都会在初始化前后批量被插入特定行为。
XML配置如下,
1 <bean id="chinese" class="spi.Chinese" 2 init-method="init" p:axe-ref="steelAxe" p:beanName="依赖注入的值" /> 3 <bean class="spi.MyBeanPostProcessor" />
测试代码,
1 public static void test8() { 2 ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 3 Person p = ctx.getBean("chinese", Person.class); 4 p.useAxe(); 5 }
执行结果,
1 Bean后处理器在初始化之前对 messageSource 进行增强处理... 2 Bean后处理器在初始化之后对 messageSource 进行增强处理... 3 Bean后处理器在初始化之前对 stoneAxe 进行增强处理... 4 Bean后处理器在初始化之后对 stoneAxe 进行增强处理... 5 Bean后处理器在初始化之前对 steelAxe 进行增强处理... 6 Bean后处理器在初始化之后对 steelAxe 进行增强处理... 7 Bean后处理器在初始化之前对 spi.EmailNotifier#0 进行增强处理... 8 Bean后处理器在初始化之后对 spi.EmailNotifier#0 进行增强处理... 9 Bean后处理器在初始化之前对 getContextViaBean 进行增强处理... 10 Bean后处理器在初始化之后对 getContextViaBean 进行增强处理... 11 Bean后处理器在初始化之前对 getField 进行增强处理... 12 Bean后处理器在初始化之后对 getField 进行增强处理... 13 Spring正在执行默认构造函数构造Chinese实例... 14 依赖注入的值:Spring正在执行setBeanName()方法注入依赖关系... 15 Bean后处理器在初始化之前对 chinese 进行增强处理... 16 正在执行初始化方法afterPropertiesSet... 17 正在执行初始化方法init... 18 Bean后处理器在初始化之后对 chinese 进行增强处理... 19 Bean后处理器将Chinese.beanName修改为‘Java编程‘. 20 Java编程:Spring正在执行setBeanName()方法注入依赖关系... 21 我打算去砍点柴火 22 修改beanName=Java编程,钢斧砍柴好快
从执行结果可以看到,受BeanPostProcessor影响,所有Bean都被插入了两条特定行为,chinese Bean由于额外实现了InitializingBean接口而多了两条额外行为。
另外可以看到虽然在配置文件中chinese的beanName被注入的是“依赖注入的值”,但是初始化之后它又被修改成了“Java编程”,所以setBeanName也被调用了两次。
从上面的例子可以看出,BeanPostProcessor接口的作用就是对容器bean进行批量处理,实际中Spring的这种后处理很有用,通常用来实现代理器,
例如BeanNameAutoProxyCreator是根据Bean实例的name属性,创建Bean实例的代理。
DefaultAdvisorProxyCreator是根据提供的Advisor对容器所有Bean实例创建代理。
原文:http://www.cnblogs.com/fysola/p/6366238.html