前言


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

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

  这篇博客主要给大家讲一下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. Orchard Platform v1.8 发布

    发布说明: 1. 添加Json格式数据文件支持.2. 彻底删除了Settings, Modules, Themes模块.3. 删除了默认的ContentType,Site和User.4. 支持空库(无 ...

  2. Xamarin开发Android笔记:TextView行间距设定

    TextView 在使用TextView的时候会遇到调整行间距的问题,可通过Layout文件添加属性完成,具体属性如下: //设置行间距,如”3dp”. android:lineSpacingExtr ...

  3. TypeScript的全部资料,以后都放这儿了

    很早之前就听说TypeScript了(以下简称TS),但总是用难以抽出时间给自己找到这个冠冕堂皇的理由.最近又心血来潮,打算写TS的博客了,毕竟TS核心开发者也是C#之父,像我这么热爱C#的人,怎么可 ...

  4. Mac 快捷键整理

    Mac 快捷键整理 文本编辑 适用于文本编辑器,浏览器等 跳到页首 cmd + ↑ 类似windows下的 ctrl + home 跳到页尾 cmd + ↓ 类似windows下的 ctrl + en ...

  5. APU平台DirectX 12性能测试:超级大惊喜!

    APU平台DirectX 12性能测试:超级大惊喜! 转自:http://www.ithome.com/html/digi/129840.htm [size=1pc]微软将会在接下来的GDC 2015 ...

  6. atitit.提升开发效率---使用服务器控件生命周期 asp.net 11个阶段 java jsf 的6个阶段比较

    atitit.提升开发效率---使用服务器控件生命周期  asp.net 11个阶段  java jsf 的6个阶段比较 如下列举了服务器控件生命周期所要经历的11个阶段. (1)初始化-- --在此 ...

  7. atitit.hbnt orm db 新新增更新最佳实践o99

    atitit.hbnt orm db 新新增更新最佳实践o99 1. merge跟个save了. 1 2. POJO对象处于游离态.持久态.托管态.使用merge()的情况. 1 3. @Dynami ...

  8. CAS 实现单点登录 .NET MVC

    单点登录 Single Sign On,简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 单点登录原理 ...

  9. Velocity模板引擎入门

    类似于PHP中的Smarty,Velocity是一个基于Java的模板引擎(template engine).它允许任何人仅仅简单的使用模板语言(template language)来引用由java代 ...

  10. Maven学习总结(四)——Maven核心概念--转载

    一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平面中唯一的一点. 1.2.Maven坐标主要组成 groupId:组织标识(包名) artifactId:项目名称 ver ...