Spring进阶教程之在ApplicationContext初始化完成后重定义Bean
之前遇到一个很有意思的问题:我需要批量重定义特定类型的由Spring容器托管的Bean。具体体现在,我有很多控制器类(Controller)和校验器类(Validator),我希望他们都是多例(Prototype)的,而Spring默认创建实例是单例(Singleton)的。有朋友可能要问:为什么不自己在Bean定义时加参数呢@Scope("prototype")?我的回答很简单:懒……。因为我的Bean声明是这样的:
那么我就没法很精确得去设置控制器和校验器的类实例为多例,因为我这里很笼统。
接下来我们详解怎样使用代码实现设置特定Bean定义的修改。
我们可以监听一个Spring的ApplicationContext的事件来让Spring的Bean容器配置完成后通知我们来处理一下。
<bean id="beanDefineConfigue" class="com.xx.yy.zz.BeanDefineConfigue"></bean>
1 public class BeanDefineConfigue implements ApplicationListener<ContextRefreshedEvent> { 2 3 @Override 4 public void onApplicationEvent(ContextRefreshedEvent event) { 5 6 } 7 }
ContextRefreshedEvent是“Event raised when an ApplicationContext gets initialized or refreshed.(当ApplicationContext初始化完成或刷新完成后产生的事件)”
当然,我们可以在onApplicationEvent函数内“搞事儿”了!
1 public void onApplicationEvent(ContextRefreshedEvent event) { 2 ConfigurableApplicationContext context = (ConfigurableApplicationContext) event.getApplicationContext(); 3 DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getBeanFactory(); 4 // 控制器 5 String[] controllers = factory.getBeanNamesForAnnotation(Controller.class); 6 if(controllers != null) { 7 for(String controllerBeanName : controllers) { 8 BeanDefinition beanDefine = factory.getBeanDefinition(controllerBeanName); 9 String scope = beanDefine.getScope(); 10 if(scope == null || !scope.equals(ConfigurableBeanFactory.SCOPE_PROTOTYPE)) { 11 beanDefine.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE); 12 factory.registerBeanDefinition(controllerBeanName, beanDefine); 13 } 14 } 15 } 16 // 校验器 17 Object[] validators = factory.getBeanNamesForType(Validator.class); 18 if(validators != null) { 19 for(Object _validatorBeanName : validators) { 20 String validatorBeanName = String.valueOf(_validatorBeanName); 21 BeanDefinition beanDefine = factory.getBeanDefinition(validatorBeanName); 22 String scope = beanDefine.getScope(); 23 if(scope == null || !scope.equals(ConfigurableBeanFactory.SCOPE_PROTOTYPE)) { 24 beanDefine.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE); 25 factory.registerBeanDefinition(validatorBeanName, beanDefine); 26 } 27 } 28 } 29 }