首先对BeanPostProcessor,BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor做个整理。
BeanPostProcessor: Spring容器Bean的后置回调接口,即每个Bean在实例化之前都会调用BeanPostProcessor里的postProcessBeforeInitialization和postProcessAfterInitialization方法。
测试实例:
package com.harry.spring4.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class TestBeanPostPocesser implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--postProcessBeforeInitialization---" + bean.getClass());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("--postProcessAfterInitialization--" + bean.getClass());
return bean;
}
}
运行结果:
BeanFactoryPostProcessor: 容器的初始化回调,只会执行一次,在BeanFatory初始化后,Bean的初始化之前(通过Bean的Init方法测试)执行
测试用例:
package com.harry.spring4.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* 容器的初始化回调
* 只会执行一次,在BeanFactory初始化完成之后,只会出发一次,可以在postProcessBeanFactory方法中做相关处理
* 在Bean初始化之前就会执行(Bean的init方法之前)
* @author Harry Wan
*
*/
@Component
public class TestFactoryPostProcessor implements BeanFactoryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("容器中一共有:" + beanFactory.getBeanDefinitionCount() + " 个Bean!");
}
}
运行结果:
BeanDefinitionRegistryPostProcessor: 可以获取到BeanDefinitionRegistry对象,通过BeanDefinitionRegistry对象来实现Bean的动态注入
测试用例:
package com.harry.spring4.demo3;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;
/**
* BeanDefinitionRegistryPostProcessor可以获取到BeanDefinitionRegistry对象
* BeanDefinitionRegistry可以动态的注入Bean到Spring容器中
* @author Harry Wan
*
*/
@Component
public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// TODO Auto-generated method stub
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinitionBuilder builder1 = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);
registry.registerBeanDefinition("xyz", builder1.getBeanDefinition());
for (int i = 0; i < 5; i++) {//这里动态注入5个Bean
//获取基于MyBean2 的定义
BeanDefinitionBuilder builder2 = BeanDefinitionBuilder.genericBeanDefinition(MyBean2.class);
builder2.addPropertyValue("name", "zhangsan" + i);
//属性依赖MyBean,确保MyBean一再容器中
//builder2.addPropertyReference("abc", "createMyBean");//@Bean(name="createMyBean")
builder2.addPropertyReference("abc", "xyz");//动态手动注入MyBean实例
registry.registerBeanDefinition(i + "", builder2.getBeanDefinition());
}
}
}
package com.harry.spring4.demo3;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyDemo3 {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.harry.spring4.demo3");
applicationContext.registerBeanDefinition("instanceMyBeanType2", BeanDefinitionBuilder.genericBeanDefinition(MyBean.class).getBeanDefinition());
System.out.println(applicationContext.getBeansOfType(MyBean2.class));
System.out.println(applicationContext.getBeansOfType(MyBean.class));
applicationContext.close();
}
}
package com.harry.spring4.demo3;
public class MyBean2 {
private MyBean abc;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyBean getAbc() {
return abc;
}
public void setAbc(MyBean abc) {
this.abc = abc;
}
@Override
public String toString() {
return "MyBean2 [abc=" + abc + ", name=" + name + "]";
}
}
总结:这里通过BeanDefinitionRegistry对象向Spring容器动态注入Bean,利用BeanDefinitionBuilder获取目标Bean的定义BeanDefinition,在注入Bean的同时,可以设置属性的值,以及属性的引用,在设置属性的引用时,要注意被引用的Bean的实例已经配置在容器中,所引用的Bean的实例也可以通过动态注入到Spring容器中或者通过注解注入。
applicationContext.registerBeanDefinition("instanceMyBeanType2", BeanDefinitionBuilder.genericBeanDefinition(MyBean.class).getBeanDefinition());
你也可以通过ApplicationContext提供的手动注入方式注入,其参数以及原理和实现BeanDefinitionRegistryPostProcessor借口一致。