spring-第十二篇之两种后处理器
1、扩展IoC容器使用后处理器扩展
bean后处理器:对容器中的bean进行后处理,也就是额外的加强。
容器后处理:对IoC容器进行后处理,增强容器功能。
2、bean后处理器
负责处理容器中的所有bean。
bean后处理器必须实现BeanPostProcessor接口,提供非方法有:
Object postProcessBeforeInitialization(Object bean,String name)throws BenasException:该方法第一个参数是系统即将进行后处理的bean实例,第二个参数是bean的配置id。在目标bean初始化之前被回调。
Object postProcessAfterInitialization(Object bean,String name)throws BenasException:该方法第一个参数是系统即将进行后处理的bean实例,第二个参数是bean的配置id。在目标bean初始化之后被回调。
举个例子:
MyBeanPostProcessor.java
package com.lfy.bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String name) throws BeansException { System.out.println("bean后处理器在初始化之后对"+name+"进行增强处理..."); return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { System.out.println("bean后处理器在初始化之前对"+name+"进行增强处理..."); return bean; } }
Chinese.java
package com.lfy.bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class Chinese implements InitializingBean,DisposableBean,BeanNameAware,ApplicationContextAware { private ApplicationContext ctx; private String beanID; private String someBodyName; public Chinese() { System.out.println("-----无参构造器-----"); } @Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.ctx=ctx; System.out.println("-----获取ApplicationContext容器ctx-----"); } @Override public void setBeanName(String name) { this.beanID=name; System.out.println("-----获取bean id-----"); } /** * 生命周期方法afterPropertiesSet */ @Override public void afterPropertiesSet() throws Exception { System.out.println("-----依赖关系注入之后,生命周期方法afterPropertiesSet-----"); } /** * 生命周期方法init */ public void init() { System.out.println("-----依赖关系注入之后,生命周期方法init-----"); } /** * 生命周期方法destory */ @Override public void destroy() throws Exception { System.out.println("-----bean销毁之前destroy-----"); } /** * 生命周期方法close */ public void close() { System.out.println("-----bean销毁之前close-----"); } /** * setter方法 * @param name */ public void setSomeBodyName(String name) { this.someBodyName=name; System.out.println("-----property注入属性setter方法-----"+someBodyName); } }
beans.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 --> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="chinese" class="com.lfy.bean.Chinese" init-method="init" destroy-method="close"> <property name="someBodyName" value="至尊宝"/> </bean> <bean class="com.lfy.bean.MyBeanPostProcessor"/> </beans>
SpringTest.java
package com.lfy.main; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lfy.bean.Chinese; /** * * @author lfy * */ public class SpringTest { public static void main(String[] args) { AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); Chinese chin=ctx.getBean("chinese", Chinese.class); ctx.registerShutdownHook(); System.exit(0); } }
运行结果:
总结:容器会自动将实现了BeanPostProcessor接口的bean注册为后处理器。它们之间执行的先后顺序如上。后处理会在每个bean创建时自动执行。
使用BeanFactory作为spring容器,必须手动注册后处理器。
bean后处理器的用处:
1》BeanNameAutoProxyCreator:根据bean实例的name属性,创建bean实例的代理。
2》DefaultAdvisorAutoProxyCreator:根据提供的Advisor,对容器中的所有bean实例创建代理。
3、容器后处理器
负责处理容器本身。
容器后处理器必须实现BeanFactoryPostProcessor接口,并实现postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory),在该方法中对spring容器进行自定义扩展。使用BeanFactory的容器需要手动注册后处理bean。
举个例子:
MyContainerPostProcessor.java
package com.lfy.bean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class MyContainerPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("容器后处理器...spring容器是"+beanFactory); } }
beans.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 --> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- 遇到了个问题,destory-method="close"不能出现在<bean.../>,暂未明白原因 --> <bean id="chinese" class="com.lfy.bean.Chinese" init-method="init" destroy-method="close"> <property name="someBodyName" value="至尊宝"/> </bean> <bean class="com.lfy.bean.MyBeanPostProcessor"/> <bean class="com.lfy.bean.MyContainerPostProcessor"/> </beans>
运行结果:
总结:如果有需要,可以配置多个容器后处理器,多个容器后处理器可设置order属性来控制容器后处理器的执行顺序,但需要容器后处理器实现Ordered接口。