Spring动态加载Bean

发表时间:2018-06-13 10:47:15 浏览量( 7 ) 留言数( 0 )

学习目标:

1、了解Spring的动态加载Bean的方式


学习过程:

    通过getBean来获得对象,但这些对象都是事先定义好的,我们有时候要在程序中动态的加入对象.因为如果采用配置文件或者注解,我们要加入对象的话,还要重启服务,如果我们想要避免这一情况就得采用动态处理bean,包括:动态注入,动态删除。

    在具体进行代码实现的时候,我们要知道,Spring管理bean的对象是BeanFactory,具体的是DefaultListableBeanFactory,在这个类当中有一个注入bean的方法:  registerBeanDefinition,在调用registerBeanDefinition方法时,需要BeanDefinition参数,那么这个参数怎么获取呢?Spring提供了BeanDefinitionBuilder可以构建一个BeanDefinition,那么我们的问题就是如何获取BeanFactory了,这个就很简单了,只要获取到ApplicationContext对象即可获取到BeanFacory了。

    写一个工具类,获得ApplicationContenxt

@Component
public class SpringContextUtil implements ApplicationContextAware {
	private static ApplicationContext applicationContext;

	// 获取上下文
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	// 设置上下文
	public void setApplicationContext(ApplicationContext applicationContext) {
		SpringContextUtil.applicationContext = applicationContext;
	}

	// 通过名字获取上下文中的bean
	public static Object getBean(String name) {
		return applicationContext.getBean(name);
	}

	// 通过类型获取上下文中的bean
	public static Object getBean(Class<?> requiredType) {
		return applicationContext.getBean(requiredType);
	}
}


    先定义一个普通的类,默认没有给spring容器加载的

public class TestBiz {
	private TestHasBiz testHasBiz;//这个需要注入的,注意需要有set方法
	public void test() {
		System.out.println(testHasBiz);
	}
	public void setTestHasBiz(TestHasBiz testHasBiz) {
		this.testHasBiz = testHasBiz;
	}
}


再一下一个注册Bean的类,该类是交给Spring容器管理的,提供一个注册方法。

@Service
public class TestRegister {

	public void register() {
		// 将applicationContext转换为ConfigurableApplicationContext
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringContextUtil
				.getApplicationContext();

		// 获取bean工厂并转换为DefaultListableBeanFactory
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext
				.getBeanFactory();

		// 通过BeanDefinitionBuilder创建bean定义
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(TestBiz.class);

		// 设置属性userService,此属性引用已经定义的bean:userService,这里userService已经被spring容器管理了.
		beanDefinitionBuilder.addPropertyReference("testHasBiz", "testHasBiz");

		// 注册bean
		defaultListableBeanFactory.registerBeanDefinition("testBiz",
				beanDefinitionBuilder.getBeanDefinition());

        
		//TestBiz testBiz = (TestBiz) SpringContextUtil.getBean("testBiz");

		//System.out.println(testBiz);

		// 删除bean.
		// defaultListableBeanFactory.removeBeanDefinition("testService");
	}

}


在测试类里面试一下

@RunWith(SpringRunner.class)
@SpringBootTest(classes=SpringfirstApplication.class)
public class SpringfirstApplicationTests {
	
	@Autowired
	private TestRegister testRegister;

	@Test
	public void contextLoads() {
		testRegister.register();
		TestBiz testBiz = (TestBiz) SpringContextUtil.getBean("testBiz");
	}

}