一、使用BeanPostProcessor定制bean
BeanPostProcessor接口定义了回调方法,你可以实现它来提供你自己的(或重载容器的默认)实例化逻辑,依赖解析逻辑等等。如果你想在Spring容器完成实例化,配置和初始化bean之后实现一些自定义逻辑,可以插入一个或多个BeanPostProcessor实现。
你可以配置多个BeanPostProcessor实例,你可以通过设置order属性来控制这些BeanPostProcessor的执行顺序。只有当BeanPostProcessor实现了“Ordered”接口时,才可以设置此属性;如果你写自己的BeanPostProcessor,你应该考虑实现“Ordered”接口。
BeanPostProcessor操作bean(或对象)实例; 也就是说,Spring IoC容器实例化一个bean实例,然后BeanPostProcessor做他们的工作.BeanPostProcessor的作用域是每个容器。 这仅在使用容器层次结构时才会用到这个。 如果你在一个容器中定义一个BeanPostProcessor,它将只对该容器中的bean进行后处理。 换句话说,在一个容器中定义的bean不会被另一个容器中定义的BeanPostProcessor进行后处理,即使两个容器都是同一层次结构的一部分。
org.springframework.beans.factory.config.BeanPostProcessor接口恰好包含两个回调方法。当这样的类在容器内注册为post-processor,对于由容器创建的每个bean实例,容器创建所有bean,在容器初始化方法(比如InitializingBean的afterProperieSet()方法和其他所有的声明的init方法)和所有bean 初始化回调之前,运行post-processor回调。post-processor可以对bean实例采取任何操作,包括完全忽略回调。 bean post-processor通常检查回调接口或者可以用代理包装bean。一些Spring AOP基础结构类被实现为bean post-processor,以便提供代理包装逻辑。
一个ApplicationContext 自动检测在配置元数据中定义的实现BeanPostProcessor接口的任何bean。 ApplicationContext将这些bean注册为后处理器,以便稍后在创建bean时调用它们。 Bean后处理器可以像任何其他bean一样部署在容器中(直接使用<bean>)。
注意,当在配置类上使用@Bean工厂方法声明BeanPostProcessor时,工厂方法的返回类型应该是实现类本身或至少是org.springframework.beans.factory.config.BeanPostProcessor接口,清楚地表明该bean的后处理器性质。否则,ApplicationContext将不能在完全创建它之前通过类型自动检测它。因为BeanPostProcessor需要尽早的实例化,以便应用于上下文中其他bean的初始化,所以这种尽早的类型检测是至关重要的。
二、使用BeanFactoryPostProcessor定制配置元数据
    我们将要看到的下一个扩展点是“org.springframework.beans.factory.config.BeanFactoryPostProcessor”。这个接口的语义类似于BeanPostProcessor,其中一个主要区别是:BeanFactoryPostProcessor对* bean配置元数据*操作;也就是说,Spring IoC容器允许BeanFactoryPostProcessor读取配置元数据,并可能在容器实例化(除BeanFactoryPostProcessor之外的任何)bean之前改变它。
你可以配置多个BeanFactoryPostProcessors,你可以通过设置orderproperty来控制这些BeanFactoryPostProcessor的执行顺序。但是,如果BeanFactoryPostProcessor实现了 Ordered接口,则只能设置此属性。如果你写自己的“BeanFactoryPostProcessor”,你应该考虑实现 Ordered接口。
如果你想改变实际的bean 实例(即从配置元数据创建的对象),那么你需要使用一个BeanPostProcessor述。虽然在技术上可以使用BeanFactoryPostProcessor(例如,使用BeanFactory.getBean())中的bean实例,这样做会导致提前的bean实例化,违反标准容器生命周期。这可能导致负面的副作用,如绕过bean后处理。此外,BeanFactoryPostProcessors的作用域也是在各自的容器内。这仅在使用容器层次结构时才相关。如果你在一个容器中定义一个BeanFactoryPostProcessor,它只会应用于该容器中的bean定义。一个容器中的Bean定义不会被另一个容器中的BeanFactoryPostProcessor进行后置处理,即使这两个容器都是同一层次结构的一部分。
接下里用代码来看看BeanPostProcessor和BeanFactoryPostProcessor
<!-- ContainnerDevelopment --><!-- 支持Spring注解 --><bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" /><!-- 注册一个BeanPostProcessor --><bean id="postProcessor" class="com.jay.document.containnerDevelop.PostProcessor"/><!-- 注册一个BeanFactoryPostProcessor --><bean id="factoryPostProcessor" class="com.jay.document.containnerDevelop.FactoryPostProcessor"/><!-- 普通bean --><bean id="beanFactoryPostProcessorTest" class="com.jay.document.containnerDevelop.BeanFactoryPostProcessorTest"><property name="name" value="张三"/><property name="sex" value="男"/></bean> 
 上面的postProcessor实现了BeanPostProcessor接口,FactoryPostProcessor实现了BeanFactoryPostProcessor。
postProcessor:
public class PostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("后置处理器AfterInitialization()方法处理bean=【"+beanName+"】 开始");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return bean;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("后置处理器BeforeInitialization()方法处理bean=【"+beanName+"】完毕!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return bean;}} 
 FactoryPostProcessor:
public class FactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {System.out.println("--->调用了BeanFactoryPostProcessor");String[] beanStr = configurableListableBeanFactory.getBeanDefinitionNames();for (String beanName : beanStr) {//这里输出  看看Bean配置的顺序 System.out.println("循环的beanName-->>"+beanName);// 这里只改变beanFactoryPostProcessorTest的属性if ("beanFactoryPostProcessorTest".equals(beanName)) {BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(beanName);MutablePropertyValues m = beanDefinition.getPropertyValues();System.out.println("--->>>"+m.getPropertyValueList().toString());if (m.contains("name")) {m.addPropertyValue("name", "李白");System.out.println("--->修改了name属性初始值了");}}}}
} 
 BeanFactoryPostProcessorTest:
public class BeanFactoryPostProcessorTest implements InitializingBean,DisposableBean,BeanNameAware,BeanFactoryAware{private String name;private String sex;public String getName() {return name;}//getter  setter@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("-->调用了BeanFactoryAware的setBeanFactory方法了");}@Overridepublic void setBeanName(String arg0) {System.out.println("-->调用了BeanNameAware的setBeanName方法了");}@Overridepublic void destroy() throws Exception {System.out.println("-->调用了DisposableBean的destroy方法了");       }@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("-->调用了Initailization的afterPropertiesSet方法了");}@Overridepublic String toString() {return "BeanFactoryPostProcessorTest [name=" + name + ", sex=" + sex + "]";}
} 
 Test:
public static void main(String[] args) {System.out.println("-->Spring ApplicationContext容器开始初始化了......");ApplicationContext applicationcontext= new ClassPathXmlApplicationContext("applicationContext.xml");System.out.println("-->Spring ApplicationContext容器初始化完毕了......");//BeanLifecycle beanLifecycle =applicationcontext.getBean("beanLifecycle",BeanLifecycle.class);BeanFactoryPostProcessorTest beanFactoryPostProcessorTest=applicationcontext.getBean(BeanFactoryPostProcessorTest.class);System.out.println(beanFactoryPostProcessorTest.toString());} 
 运行结果 :
-->Spring ApplicationContext容器开始初始化了......
--->调用了BeanFactoryPostProcessor // 调用了 FactoryPostProcessor的postProcessBeanFactory方法
循环的beanName-->>myAware   //这是通过@component注解配置的bean  在读取配置是在第一个
循环的beanName-->>org.springframework.context.annotation.internalConfigurationAnnotationProcessor
循环的beanName-->>org.springframework.context.annotation.internalAutowiredAnnotationProcessor
循环的beanName-->>org.springframework.context.annotation.internalRequiredAnnotationProcessor
循环的beanName-->>org.springframework.context.annotation.internalCommonAnnotationProcessor
循环的beanName-->>container   //这是通过xml配置的bean  
循环的beanName-->>atList        //这是也通过xml配置的bean    顺序是按照配置的顺序
循环的beanName-->>org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0
循环的beanName-->>postProcessor
循环的beanName-->>factoryPostProcessor
循环的beanName-->>beanFactoryPostProcessorTest  // 这里可以看出 在bean没有实例化之前 ,就改变了 bean的属性配置 
--->>>[bean property 'name', bean property 'sex'] // BeanFactoryPostProcessor 是对读取每个bean的配置文件都有效
--->修改了name属性初始值了 //
循环的beanName-->>org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor循环的beanName-->>org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
后置处理器BeforeInitialization()方法处理bean=【myAware】完毕 // BeanPostProcessor 同样是对读取每个bean的配置文件都有效
后置处理器AfterInitialization()方法处理bean=【myAware】 开始
后置处理器BeforeInitialization()方法处理bean=【atList】完毕!
后置处理器AfterInitialization()方法处理bean=【atList】 开始
后置处理器BeforeInitialization()方法处理bean=【container】完毕!
后置处理器AfterInitialization()方法处理bean=【container】 开始
-->调用了BeanNameAware的setBeanName方法了
-->调用了BeanFactoryAware的setBeanFactory方法了//这里可以看出 BeanPostProcessor 的BeforeInitialization方法 执行 //在 Initailization的afterPropertiesSet方法之前
后置处理器BeforeInitialization()方法处理bean=【beanFactoryPostProcessorTest】完毕!
-->调用了Initailization的afterPropertiesSet方法了
后置处理器AfterInitialization()方法处理bean=【beanFactoryPostProcessorTest】 开始
-->Spring ApplicationContext容器初始化完毕了......
BeanFactoryPostProcessorTest [name=李白, sex=男] // 属性已经改变
三、 使用FactoryBean定制实例化逻辑
对象实现org.springframework.beans.factory.FactoryBean接口,则成为它本身的工厂。
FactoryBean接口是Spring IoC容器实例化逻辑的扩展点。假如初始化代码非常复杂,此时使用java编码比使用XML配置更容易表达。这种场景中,你可以创建自己的FactoryBean,在该类中编写复杂的初始化程序,然后将你的自定义FactoryBean插入到容器。
FactoryBean接口提供了三种方法:
Object getObject():返回此工厂创建的对象的实例。实例可以共享,这取决于这个工厂是返回单例还是原型。boolean isSingleton():如果这个“FactoryBean”返回单例,则返回true,否则返回false。类getObjectType():返回由getObject()方法或null返回的对象类型,如果类型不是预先知道的。
FactoryBean概念和接口在Spring框架中的许多地方使用; Spring内置的有超过50个实现。
当你需要向容器请求一个实际的FactoryBean实例本身而不是它生成的bean时,在调用ApplicationContext的getBean()方法时,用符号(&)作为前缀。所以对于给定的FactoryBean,id为myBean,在容器上调用getBean(“myBean”)会返回FactoryBean所产生的bean;而调用getBean(“&myBean”)返回FactoryBean实例本身。
FactoryBean的核心就在于通过getObject方法可以获取的是它所生产的对象,所以我们在Proxy创建代理对象的时候就比较方便。还有一些bean,如果通过配置的方式,会显得比较麻烦和复杂,那么这时候适当的采用编码方式在某些场合下还是挺不错的。
给个小例子(来自此博)
- </span>public interface FactoryBean<T> {
 - //返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。
 - T getObject() throws Exception;
 - //返回FactoryBean创建的bean类型。
 - Class<?> getObjectType();
 - //返回由FactoryBean创建的bean实例的作用域是singleton还是prototype。
 - boolean isSingleton();
 - }
 
- public class Person {
 - private String name;
 - private String address;
 - private int age;
 - }
 
- <bean id="personBean" class="com.gh.MavenTest.Person">
 - <property name="name" value="gh1" />
 - <property name="address" value="address1" />
 - <property name="age" value="28" />
 - </bean>
 
那么现在我们可以通过getBean("personBean")来获取该对象。那么我们来看下如果通过实现FactoryBean以后该怎么写呢?来看下我们的PersonFactoryBean的代码:
- public class PersonFactoryBean implements FactoryBean<Person>{
 - private String personInfo;
 - public Person getObject() throws Exception {
 - Person person = new Person () ;
 - String [] infos = personInfo.split ( "," ) ;
 - person.setName(infos[0]);
 - person.setAddress(infos[1]);
 - person.setAge(Integer.parseInt(infos[2]));
 - return person;
 - }
 - public Class<Person> getObjectType() {
 - return Person.class;
 - }
 - public boolean isSingleton() {
 - return true;
 - }
 - }
 
我们看到,这里PersonFactoryBean实现了FactoryBean接口,那么自然也要实现它定义的方法。这里我们是通过一个personInfo字符串解析得到Person对象,那么我们在配置Spring的时候就可以这么配置:
- <bean id="personFactory" class="com.hik.MavenTest.PersonFactory">
 - <property name="personInfo" value="gh2,address2,22"></property>
 - </bean>