前言


  很久没有写博客了,也是两个原因:一是自己觉得一直在班门弄斧,其实自己没什么技术可言;二是很多朋友的问题实际上可以自行解决,我经常觉得不该我来过问,或者是有时候我认为技术还得靠自己钻研,我一两句话不能让各位醍醐灌顶……

  不过还是偶尔做一下记录,免得博客界渐渐就把我淡忘了。

  这篇博客主要给大家讲一下Spring中如何批量修改Bean的定义。

应用场景

  我之前遇到一个很有意思的问题:我需要批量重定义特定类型的由Spring容器托管的Bean。具体体现在,我有很多控制器类(Controller)和校验器类(Validator),我希望他们都是多例(Prototype)的,而Spring默认创建实例是单例(Singleton)的。有朋友可能要问:为什么不自己在Bean定义时加参数呢@Scope("prototype")?我的回答很简单:懒……。因为我的Bean声明是这样的:

  

  

  那么我就没法很精确得去设置控制器和校验器的类实例为多例,因为我这里很笼统。

  接下来我们详解怎样使用代码实现设置特定Bean定义的修改。

ApplicationListener-ContextRefreshedEvent

  我们可以监听一个Spring的ApplicationContext的事件来让Spring的Bean容器配置完成后通知我们来处理一下。

<bean id="beanDefineConfigue" class="com.xx.yy.zz.BeanDefineConfigue"></bean>
 public class BeanDefineConfigue implements ApplicationListener<ContextRefreshedEvent> {

     @Override
public void onApplicationEvent(ContextRefreshedEvent event) { }
}

  ContextRefreshedEvent是“Event raised when an ApplicationContext gets initialized or refreshed.(当ApplicationContext初始化完成或刷新完成后产生的事件)”

  当然,我们可以在onApplicationEvent函数内“搞事儿”了!

BeanFactory-BeanDefinition-registerBeanDefinition

 public void onApplicationEvent(ContextRefreshedEvent event) {
ConfigurableApplicationContext context = (ConfigurableApplicationContext) event.getApplicationContext();
DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getBeanFactory();
// 控制器
String[] controllers = factory.getBeanNamesForAnnotation(Controller.class);
if(controllers != null) {
for(String controllerBeanName : controllers) {
BeanDefinition beanDefine = factory.getBeanDefinition(controllerBeanName);
String scope = beanDefine.getScope();
if(scope == null || !scope.equals(ConfigurableBeanFactory.SCOPE_PROTOTYPE)) {
beanDefine.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
factory.registerBeanDefinition(controllerBeanName, beanDefine);
}
}
}
// 校验器
Object[] validators = factory.getBeanNamesForType(Validator.class);
if(validators != null) {
for(Object _validatorBeanName : validators) {
String validatorBeanName = String.valueOf(_validatorBeanName);
BeanDefinition beanDefine = factory.getBeanDefinition(validatorBeanName);
String scope = beanDefine.getScope();
if(scope == null || !scope.equals(ConfigurableBeanFactory.SCOPE_PROTOTYPE)) {
beanDefine.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
factory.registerBeanDefinition(validatorBeanName, beanDefine);
}
}
}
}

  可以看到,核心代码其实很少,也很容易懂!我针对控制器类和校验器类的所有Bean定义(使用getBeanNamesForType函数可以获取给定类型及其子类型的所有Bean定义;上文对Controller类型的检测是使用了Spring的@Controller,这是因为我个人的业务需求不一样,大家注意,beanfactory中的各种方法大家查看API灵活使用),检测到它们scope不为prototype时强制重设!

说在结尾


  我一直跟很多向我咨询Spring运用的朋友们说起:先把Spring看成一个Hashtable,它存了很多键值,就是Bean定义(包括Bean关系等等);其次是Spring不会凭空产生,更不会凭空为你托管对象,我们使用Spring的方式最终都是{new XXYYZZApplicationContext().getBean(XXYYZZ)},你在web.xml中定义的ContextLoaderListener,或者是其他中间件(Struts等)。

  “万事万物都有其源头。”所以,如果观看此篇博文的朋友进行单元测试时发现自动注入等功能未实现,请看看你是否为Spring容器创建了对象。

联系我,一起交流


欢迎您移步我们的交流群,无聊的时候大家一起打发时间:

或者通过QQ与我联系:

(最后编辑时间2015-12-31 16:22:53)

Spring进阶教程之在ApplicationContext初始化完成后重定义Bean的更多相关文章

  1. Spring 系列教程之 bean 的加载

    Spring 系列教程之 bean 的加载 经过前面的分析,我们终于结束了对 XML 配置文件的解析,接下来将会面临更大的挑战,就是对 bean 加载的探索.bean 加载的功能实现远比 bean 的 ...

  2. Spring Security教程之Jsp标签(八)

    目录 1.1     authorize 1.2     authentication 1.3     accesscontrollist Spring Security也有对Jsp标签的支持的标签库 ...

  3. Spring Security教程之Jsp标签(四)

    目录 1.1     authorize 1.2     authentication 1.3     accesscontrollist Spring Security也有对Jsp标签的支持的标签库 ...

  4. 迅为4412开发板Linux驱动教程之GPIO的初始化

    视频下载地址:http://pan.baidu.com/s/1c06oiti GPIO的初始化 • 在内核源码目录下使用命令“ls drivers/gpio/*.o”,可以看到“gpio-exynos ...

  5. Spring Security教程之session管理(十一)

    1.1     检测session超时 1.2     concurrency-control 1.3     session 固定攻击保护 Spring Security通过http元素下的子元素s ...

  6. Spring Security教程之session管理

    1.1     检测session超时 1.2     concurrency-control 1.3     session 固定攻击保护 Spring Security通过http元素下的子元素s ...

  7. Vue 进阶教程之:详解 v-model

    分享 Vue 官网教程上关于 v-model 的讲解不是十分的详细,写这篇文章的目的就是详细的剖析一下, 并介绍 Vue 2.2 v-model改进的地方,然后穿插的再说点 Vue 的小知识. 在 V ...

  8. 《STM32CubeMX配置STM32H743XI工程》第一讲《初始化UART,重定义printf函数,点亮一个LED灯》

    1.打开STM32CubeMX软件->新建一个工程(软件自行到ST官网下载安装) 2.输入对应的芯片型号(本次基于野火STM32H743XI Pro 开发板)点击Start Project生成项 ...

  9. SpringBoot 源码解析 (三)----- Spring Boot 精髓:启动时初始化数据

    在我们用 springboot 搭建项目的时候,有时候会碰到在项目启动时初始化一些操作的需求 ,针对这种需求 spring boot为我们提供了以下几种方案供我们选择: ApplicationRunn ...

随机推荐

  1. Windows下安装MinGW,编译c/c++时出现cannot find -lpthread解决办法

    由于Mingw下没有带pthread库,所以在eclipse中设置多线程动态链接库,也不管用.需要自己下载, ftp://sourceware.org/pub/pthreads-win32/pthre ...

  2. mongo(五)副本集

    mongo(五)副本集 配置文件 1-3为三个存储节点,其实一个为Primary,两个secondary作为备份,4为仲裁节点 # mongod.conf #where to log logpath= ...

  3. DDD基本概念

    一条箴言是:如果值对象是可共享的,那么它们应该是不可变的.值对象应该保持很小.很简单 极力推荐将值对象实现为不可变的.它们由一个构造器创建,并且在它们的生命周期内永远不会被修改.当你想要得到这个对象的 ...

  4. [BTS] Deploy Command

    BizTalkDeploymentTools.AddResource.bat @Echo OFF SET ApplicationName=%~1 SET ComponentType=%~2 SET C ...

  5. 使用Lucene.NET实现数据检索功能

    引言     在软件系统中查询数据是再平常不过的事情了,那当数据量非常大,数据存储的媒介不是数据库,或者检索方式要求更为灵活的时候,我们该如何实现数据的检索呢?为数据建立索引吧,利用索引技术可以更灵活 ...

  6. paip.截取字符串byLastDot方法总结uapi python java php c# 总结

    paip.截取字符串byLastDot方法总结uapi python java php c# 总结 ========uapi   left_byLastDot   right_byLastDot 目前 ...

  7. paip.快捷方式分组管理最佳实践ObjectDock

    paip.快捷方式分组管理最佳实践ObjectDock /////挑选:除了od,还有个Berokyo ,但是bk无crash..只能使用1月.. Jumplist_Launcher_v7.2_rep ...

  8. 套路!从Ruby 到 Cocoapods的发布

    前言: 现在的社会讲究的是套路,作为一名iOS工程师, 一言不合我要发套路了! 一.Ruby(ruby环境已经安装了的朋友可以跳过这一点) 准备: Mac OSX 安装xcode,它会帮你安装好 Un ...

  9. WordPress安装使用问题记录

    本文记录在使用WordPress过程中的问题和解决. 安装 比较顺利没有问题,具体如下(CentOS 6.5,DO的CentOS7 image里默认的yum源没有mysql-serve比较奇怪r): ...

  10. ASP.NET MVC中实现多个按钮提交的几种方法

    有时候会遇到这种情况:在一个表单上需要多个按钮来完成不同的功能,比如一个简单的审批功能. 如果是用webform那不需要讨论,但asp.net mvc中一个表单只能提交到一个Action处理,相对比较 ...