------------恢复内容开始------------
一、BeanPostProcessor
BeanPostProcessor是一个IOC容器提供的一个扩展接口,用于扩展IOC容器的功能,该接口的作用是能够在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。这里的初始化方法指的是bean默认的或者自定义的一些初始化方法。
接口代码展示:
public interface BeanPostProcessor { //bean初始化方法调用前被调用(前置处理) Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; //bean初始化方法调用后被调用(后置处理) Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
方法的工作时机:
使用该接口的方法是:
第一步:定义一个类,实现该接口并实现接口中的两个方法,注意这两个方法最后的返回值一定要是bean,否则后续的处理就无法获得bean从而出错。
第二步:在xml文件中配置该类,将该类配置为bean。
这样配置好之后就会在一个容器中的所有bean上起作用
代码示例:
实现BeanPostProcessor接口:
package scripting; import org.springframework.beans.factory.config.BeanPostProcessor; public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor { // simply return the instantiated bean as-is
//注意返回值一定是bean public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; // we could potentially return any object reference here... } public Object postProcessAfterInitialization(Object bean, String beanName) { System.out.println("Bean '" + beanName + "' created : " + bean.toString()); return bean; } }
xml配置
<lang:groovy id="messenger" script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy"> <lang:property name="message" value="Fiona Apple Is Just So Dreamy."/> </lang:groovy> <!-- when the above bean (messenger) is instantiated, this custom BeanPostProcessor implementation will output the fact to the system console --> <bean class="scripting.InstantiationTracingBeanPostProcessor"/>
配置BeanPostProcessor实现类的Bean时甚至不用设置id
测试:
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.scripting.Messenger; public final class Boot { public static void main(final String[] args) throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml"); Messenger messenger = ctx.getBean("messenger", Messenger.class); System.out.println(messenger); } }
输出:
Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 org.springframework.scripting.groovy.GroovyMessenger@272961
二、BeanFactoryPostProcessor
可以在运行时动态修改xml文件中bean的配置
实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
注意:BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息。
Spring提供了一些BeanFactoryPostProcessor接口的实现类,比如PropertySourcesPlaceholderConfigurer。可以使用标准 Java格式
PropertySourcesPlaceholderConfigurer
将 bean 定义中的属性值外部化到单独的文件中。Properties
这样做使部署应用程序的人员能够自定义特定于环境的属性,例如数据库 URL 和密码,而无需修改容器的主要 XML 定义文件或文件的复杂性或风险。
示例代码:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <property name="locations" value="classpath:com/something/jdbc.properties"/> </bean> <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean>
properties文件:
jdbc.driverClassName=org.hsqldb.jdbcDriver jdbc.url=jdbc:hsqldb:hsql://production:9002 jdbc.username=sa jdbc.password=root
------------恢复内容结束------------