小引:
Spring框架提供了很好的扩展性,除了可以与各种第三方框架良好整合外,其IOC容器也允许开发者进行扩展,这种扩展甚至无须实现BeanFactory或ApplicationContext接口,而是允许通过两个后处理器对IOC容器进行扩展。Spring提供了两种常用的后处理器:
① Bean后处理器:这种后处理器会对容器中的Bean进行后处理,对Bean功能进行额外加强。
② 容器后处理器:这种后处理器对IOC容器进行后处理,用于增强容器功能。
Bean后处理器:
Bean后处理器是一种特殊的Bean,这种特殊Bean并不对外提供服务,它甚至可以无须id属性,它主要负责对容器中的其他Bean执行后处理,例如为容器中的目标Bean生成代理等。
Bean后处理器会在Bean实例创建成功之后,对Bean实例进行进一步的增强处理。
Bean后处理器必须实现 BeanPostProcessor 接口,它包含两个方法:
① Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException:第一个参数是系统即将进行后处理的Bean实例,第二个参数是该Bean实例的名字。
② Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException:第一个参数是系统即将进行后处理的Bean实例,第二个参数是该Bean实例的名字。
实现该接口的Bean后处理器必须实现这两个方法,这两个方法会对容器中的Bean进行后处理,会在目标Bean初始化之前、初始化之后分别被回调,这两个方法用于对容器中的Bean实例进行增强处理。
Axe.java :
public interface Axe { public String chop(); }
SteelAxe.java :
public class SteelAxe implements Axe { @Override public String chop() { return "钢斧砍柴真快"; } public SteelAxe() { System.out.println("Spring实例化依赖Bean:SteelAxe实例..."); } }
Person.java :
public interface Person { public void useAxe(); }
Chinese.java :
public class Chinese implements Person,InitializingBean{ private Axe axe; private String name; public void setAxe(Axe axe) { System.out.println("Spring执行依赖关系注入,setAxe..."); this.axe = axe; } public void setName(String name) { System.out.println("Spring执行依赖关系注入,setName..."); this.name = name; } public Chinese() { System.out.println("Spring实例化主调Bean:Chinese实例..."); } @Override public void useAxe() { System.out.println(name+axe.chop()); } @Override public void afterPropertiesSet() throws Exception { System.out.println("正在执行初始化方法afterPropertiesSet..."); } public void init(){ System.out.println("正在执行初始化方法init..."); } }
FirstBeanPostProcessor.java :
public class FirstBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean后处理器在初始化之前对"+beanName+"进行增强处理..."); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("Bean后处理器在初始化之后对"+beanName+"进行增强处理..."); if(bean instanceof Chinese){ Chinese c=(Chinese)bean; c.setName("中国人"); } return bean; } }
bean.xml核心配置:
<bean id="chinese" class="com.bean.Chinese" init-method="init"> <property name="axe" ref="steelAxe"/> <property name="name" value="依赖注入的值"/> </bean> <bean id="steelAxe" class="com.bean.SteelAxe"/> <bean id="beanPostProcessor" class="com.bean.FirstBeanPostProcessor"/>
Test.java :
public class Test { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml"); Person p=(Person) ctx.getBean("chinese"); p.useAxe(); } }
运行Test.java,控制台输出:
容器中一旦注册了Bean后处理器,Bean后处理器就会自动启动,在容器中每个Bean创建时自动工作。从上面程序的运行结果可以看出,Bean后处理器两个方法的回调时机如下图所示:
采用ApplicationContext作为Spring容器时,无须手动注册BeanPostProcessor。但是如果采用BeanFactory作为Spring容器时,就必须手动注册BeanPostProcess,如下:
public class Test { public static void main(String[] args) { ClassPathResource resource=new ClassPathResource("bean.xml"); XmlBeanFactory factory=new XmlBeanFactory(resource); BeanPostProcessor bpp=(FirstBeanPostProcessor) factory. getBean("beanPostProcessor"); factory.addBeanPostProcessor(bpp); //注册BeanPostProcessor实例 System.out.println("程序已经实例化BeanFactory..."); Person p=(Person) factory.getBean("chinese"); System.out.println("程序中已经完成了chinese bean的实例化..."); p.useAxe(); } }
上面的例子中Bean后处理器没有起到什么实际作用,毕竟这只是个例子。实际工作中Bean后处理器完成的工作更加实际,例如生成Proxy。Spring框架本身提供了大量的Bean后处理器,这些后处理器负责对容器中Bean进行后处理。
下面是Spring提供的两个常用的后处理器:
① BeanNameAutoProxyCreator:根据Bean实例的name属性,创建Bean实例的代理。
② DefaultAdvisorAutoProxyCreator:根据提供的advisor,对容器中所有的Bean实例创建代理。
上面提供的两个Bean后处理器,都用于根据容器中配置的拦截器,创建代理Bean,代理Bean就是对目标Bean进行增强、在目标Bean的基础上进行修改得到新的Bean。