zoukankan      html  css  js  c++  java
  • Spring进阶教程之在ApplicationContext初始化完成后重定义Bean

    前言


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

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

      这篇博客主要给大家讲一下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>
    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函数内“搞事儿”了!

    BeanFactory-BeanDefinition-registerBeanDefinition

     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     }

      可以看到,核心代码其实很少,也很容易懂!我针对控制器类和校验器类的所有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容器创建了对象。

    联系我,一起交流


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

     

    或者通过QQ与我联系:点击这里给我发消息

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

  • 相关阅读:
    jquery笔记
    mysql优化三
    MYSQL优化
    mysql大表优化
    mybatis缓存机制
    mybatis主键返回语句 使用方法,就是实体类.getid即可拿到返回的id
    mybatis组合实体查询
    HTTP Status 500
    Perfmon——为什么“% Disk Time”计数器的值会大于100%?
    Lint——Android SDK提供的静态代码扫描工具
  • 原文地址:https://www.cnblogs.com/Johness/p/spring-override-beandefine-after-initialized.html
Copyright © 2011-2022 走看看