基于Spring容器Bean的动态注入

首先对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;
	}

}

运行结果:

基于Spring容器Bean的动态注入_第1张图片


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借口一致。

你可能感兴趣的:(Spring)