编程方式实现SpringBean LazyInit

背景:
工程单元测试希望和生产环境应用共用一份Spring配置文件.
生产环境应用为了客户体验使用非LazyInit模式,但是单元测试下为了当前测试提高响应时间,希望设置LazyInit.

分析源代码,得知,Spring在解析XML时,会将Bean默认配置,放入到DocumentDefaultsDefinition对象中,其中包含lazyInit.
DocumentDefaultsDefinition注释如下:
Simple JavaBean that holds the defaults specified at the <beans> level in a standard Spring XML bean definition document: default-lazy-init, default-autowire, etc

Spring是否提供了入口点,进行DocumentDefaultsDefinition的修改呢?
详见:ReaderEventListener,注释如下:
Interface that receives callbacks for component, alias and import registrations during a bean definition reading process
在BeanDefinition分析过程中,对component,alias,import registrations,defaults registrations提供一组callbacks.

接口代码如下:

 1  public   interface  ReaderEventListener  extends  EventListener {
 2 
 3       /**
 4       * Notification that the given defaults has been registered.
 5       *  @param  defaultsDefinition a descriptor for the defaults
 6       *  @see  org.springframework.beans.factory.xml.DocumentDefaultsDefinition
 7        */
 8       void  defaultsRegistered(DefaultsDefinition defaultsDefinition);
 9 
10       /**
11       * Notification that the given component has been registered.
12       *  @param  componentDefinition a descriptor for the new component
13       *  @see  BeanComponentDefinition
14        */
15       void  componentRegistered(ComponentDefinition componentDefinition);
16 
17       /**
18       * Notification that the given alias has been registered.
19       *  @param  aliasDefinition a descriptor for the new alias
20        */
21       void  aliasRegistered(AliasDefinition aliasDefinition);
22 
23       /**
24       * Notification that the given import has been processed.
25       *  @param  importDefinition a descriptor for the import
26        */
27       void  importProcessed(ImportDefinition importDefinition);
28      
29  }


接下去分析,ReaderEventListener是在哪个入口点,提供了回调.答案是XmlBeanDefinitionReader.
在AbstractXmlApplicationContext,创建了XmlBeanDefinitionReader对象,见:

 1  public   abstract   class  AbstractXmlApplicationContext  extends  AbstractRefreshableConfigApplicationContext {
 2      
 3       /**
 4       * Loads the bean definitions via an XmlBeanDefinitionReader.
 5       *  @see  org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 6       *  @see  #initBeanDefinitionReader
 7       *  @see  #loadBeanDefinitions
 8        */
 9       protected   void  loadBeanDefinitions(DefaultListableBeanFactory beanFactory)  throws  IOException {
10           //  Create a new XmlBeanDefinitionReader for the given BeanFactory.
11          XmlBeanDefinitionReader beanDefinitionReader  =   new  XmlBeanDefinitionReader(beanFactory);
12 
13           //  Configure the bean definition reader with this context's
14           //  resource loading environment.
15          beanDefinitionReader.setResourceLoader( this );
16          beanDefinitionReader.setEntityResolver( new  ResourceEntityResolver( this ));
17 
18           //  Allow a subclass to provide custom initialization of the reader,
19           //  then proceed with actually loading the bean definitions.
20          initBeanDefinitionReader(beanDefinitionReader);
21          loadBeanDefinitions(beanDefinitionReader);
22      }
23 
24  }


我们只需要去复写这个方法,在美茵肽创建XmlBeanDefinitionReader的时候,去注入EventListener即可.

扩展代码如下:
LazyInitListener.java (不管配置文件如何配置,设置默认的LazyInit为true)

public   class  LazyInitListener  implements  ReaderEventListener {

    
private   static   final  String LAZY_INIT  =   " true " ;

    @Override
    
public   void  defaultsRegistered(DefaultsDefinition defaultsDefinition) {
        
// set lazy init true
         if  (defaultsDefinition  instanceof  DocumentDefaultsDefinition) {
            DocumentDefaultsDefinition defaults 
=  (DocumentDefaultsDefinition) defaultsDefinition;
            defaults.setLazyInit(LAZY_INIT);
        }
    }

    @Override
    
public   void  aliasRegistered(AliasDefinition aliasDefinition) {
        
// no-op
    }

    @Override
    
public   void  componentRegistered(ComponentDefinition componentDefinition) {
        
// no-op
    }

    @Override
    
public   void  importProcessed(ImportDefinition importDefinition) {
        
// no-op
    }

}


LazyInitClasspathXmlApplicationContext.java (复写AbstractXmlApplicationContext,创建XmlBeanDefinitionReader的时候注入LazyInitListener)

 1  public   class  LazyInitClasspathXmlApplicationContext  extends  ClassPathXmlApplicationContext {
 2 
 3       public  LazyInitClasspathXmlApplicationContext(String location) {
 4           super (location);
 5      }
 6 
 7      @Override
 8       protected   void  loadBeanDefinitions(DefaultListableBeanFactory beanFactory)  throws  IOException {
 9           //  Create a new XmlBeanDefinitionReader for the given BeanFactory.
10          XmlBeanDefinitionReader beanDefinitionReader  =   new  XmlBeanDefinitionReader(beanFactory);
11 
12           //  Configure the bean definition reader with this context's
13           //  resource loading environment.
14          beanDefinitionReader.setResourceLoader( this );
15          beanDefinitionReader.setEntityResolver( new  ResourceEntityResolver( this ));
16 
17           //  添加的代码,设置LazyInitListener
18          beanDefinitionReader.setEventListener( new  LazyInitListener());
19 
20           //  Allow a subclass to provide custom initialization of the reader,
21           //  then proceed with actually loading the bean definitions.
22          initBeanDefinitionReader(beanDefinitionReader);
23          loadBeanDefinitions(beanDefinitionReader);
24      }
25 
26  }


演示代码如下:
TestBean:一个Spring Bean对象

public   class  TestBean {

    
public   void  init() {
        
try  {
            Thread.sleep(
5000 );
        } 
catch  (InterruptedException e) {
            
// ignore
            System.out.println(e);
        }
        System.out.println(
" TestBean Init " );
    }
}


Spring配置爱之谷文件:

1  <? xml version="1.0" encoding="UTF-8" ?>
2  < beans  xmlns ="http://www.springframework.org/schema/beans"
3      xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
4      xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" >
5 
6       < bean  id ="testBean"  class ="com.alibaba.javalab.spring.lazy.TestBean"  init-method ="init"   />
7  </ beans >


测试代码:

 1  public   class  Run {
 2 
 3       private   static   final  String CONFIG  =   " classpath:spring/bean.xml " ;
 4 
 5       public   static   void  main(String[] args) {
 6          testInit();
 7          System.out.println( " =============================== " );
 8          testLazyInit();
 9      }
10 
11       public   static   void  testInit() {
12           new  ClassPathXmlApplicationContext(CONFIG);
13      }
14 
15       public   static   void  testLazyInit() {
16           new  LazyInitClasspathXmlApplicationContext(CONFIG);
17      }
18  }



大功告成.收工. :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值