Spring點滴九:Spring bean的延遲初始化

Spring bean延遲初始化:html

官網API:spring

By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.app

譯文:默認狀況下,Spring 容器在初始化過程當中會建立和配置全部單例的bean。這種提早實例化是可取的,由於配置環境錯誤會被當即發現而不須要過多的時間。若是不採起這種行爲,能夠將單例的bean標記爲延遲初始化。一個延遲初始化的bean告訴Spring IoC容器去建立這個bean實例化對象當它第一次被調用時而不是在容器啓動時當即建立。post

在Spring Bean聲明週期這篇文檔中http://www.cnblogs.com/sishang/p/6575839.html測試

將beanLifecycle定義添加lazy-init="true"屬性this

  <bean id="beanLifecycle" class="com.test.spring.BeanLifecycle" init-method="init" destroy-method="close" lazy-init="true">
        <property name="name" value="張三"></property>
        <property name="sex" value="男"></property>
  </bean>

測試:spa

package com.test.spring;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {
    ApplicationContext applicationcontext=null;
    @Before
    public void before() {
        System.out.println("》》》Spring ApplicationContext容器開始初始化了......");
        applicationcontext= new ClassPathXmlApplicationContext(new String[]{"test1-service.xml"});
        System.out.println("》》》Spring ApplicationContext容器初始化完畢了......");
    }
    @Test
    public void  test() {
        String [] beans=applicationcontext.getBeanDefinitionNames();
        for(String beanName:beans){
            System.out.println(beanName);
        }
//BeanLifecycle beanLifecycle =applicationcontext.getBean("beanLifecycle",BeanLifecycle.class); } }

 

測試結果:code

》》》Spring ApplicationContext容器開始初始化了......
2017-03-19 16:43:58  INFO:ClassPathXmlApplicationContext-Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@18c92ff9: startup date [Sun Mar 19 16:43:58 CST 2017]; root of context hierarchy
2017-03-19 16:43:59  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]
》》》Spring ApplicationContext容器初始化完畢了......
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0
beanLifecycle
postProcessor

xml

***********htm

發現Spring IoC容器中雖然有beanLifecycle ID,可是容器並無實例化它,由於beanLifecycle的建立信息沒有被執行

**********

將測試中BeanLifecycle beanLifecycle =applicationcontext.getBean("beanLifecycle",BeanLifecycle.class)這段代碼解除註釋,beanLifecycle被第一次請求,容器會當即建立它。

------------------------------------------------------------------------------------------------------------------------------------------------

測試結果:

》》》Spring ApplicationContext容器開始初始化了......
2017-03-19 16:49:21  INFO:ClassPathXmlApplicationContext-Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@406c9125: startup date [Sun Mar 19 16:49:21 CST 2017]; root of context hierarchy
2017-03-19 16:49:21  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]
》》》Spring ApplicationContext容器初始化完畢了......
narCodeService
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0
beanLifecycle
postProcessor
》》》調用無參構造方法了
》》》調用BeanLifecycle對象null屬性set方法,設值爲:張三
》》》調用BeanLifecycle對象null屬性set方法,設值爲:男
》》》調用BeanNameAware接口setBenaName方法: beanLifecycle
》》》調用BeanFactoryAware接口setBeanFactory方法:org.springframework.beans.factory.support.DefaultListableBeanFactory@5ccc995c: defining beans [narCodeService,org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0,beanLifecycle,postProcessor]; root of factory hierarchy
》》》調用ApplicationContextAware接口setApplicationContext方法:org.springframework.context.support.ClassPathXmlApplicationContext@406c9125: startup date [Sun Mar 19 16:49:21 CST 2017]; root of context hierarchy
後置處理器處理bean=【beanLifecycle】開始
》》》註解初始化方法被調用
》》》BeanLifecycle調用了InitailizingBean的afterPorpertiesSet方法了.....
》》》init方法被調用
後置處理器處理bean=【beanLifecycle】完畢!

可是有一點須要注意就是:當一個非延遲初始化單例bean須要依賴注入一個延遲初始化bean,Spring 容器會當即建立這個延遲初始化的bean。由於它要知足單例的相關性

官網API:

However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy-initialized, the ApplicationContext creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized.

示例:

在Spring配置文件中添加以下bean定義(基於Spring Bean聲明週期這篇文檔中http://www.cnblogs.com/sishang/p/6575839.html):

<bean id="test" class="com.test.spring.Test" >
     <property name="beanLifecycle" ref="beanLifecycle"></property>
</bean>

新建Test類:

package com.test.spring;


public class Test {

    private  BeanLifecycle beanLifecycle;

    public BeanLifecycle getBeanLifecycle() {
        return beanLifecycle;
    }

    public void setBeanLifecycle(BeanLifecycle beanLifecycle) {
        this.beanLifecycle = beanLifecycle;
    }
    
}

測試:

package com.test.spring;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {
    ApplicationContext applicationcontext=null;
    @Before
    public void before() {
        System.out.println("》》》Spring ApplicationContext容器開始初始化了......");
        applicationcontext= new ClassPathXmlApplicationContext(new String[]{"test1-service.xml"});
        System.out.println("》》》Spring ApplicationContext容器初始化完畢了......");
    }
    @Test
    public void  test() {
        //BeanLifecycle beanLifecycle =applicationcontext.getBean("beanLifecycle",BeanLifecycle.class);
        String [] beans=applicationcontext.getBeanDefinitionNames();
        for(String beanName:beans){
            System.out.println(beanName);
        }
       //applicationcontext.getBean(BeanLifecycle.class);
    }
}

測試結果:

》》》Spring ApplicationContext容器開始初始化了......
2017-03-19 17:06:19  INFO:ClassPathXmlApplicationContext-Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@406c9125: startup date [Sun Mar 19 17:06:19 CST 2017]; root of context hierarchy
2017-03-19 17:06:19  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]
》》》調用無參構造方法了
》》》調用BeanLifecycle對象null屬性set方法,設值爲:張三
》》》調用BeanLifecycle對象null屬性set方法,設值爲:男
》》》調用BeanNameAware接口setBenaName方法: beanLifecycle
》》》調用BeanFactoryAware接口setBeanFactory方法:org.springframework.beans.factory.support.DefaultListableBeanFactory@76e9e1a0: defining beans [narCodeService,org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0,beanLifecycle,postProcessor,test]; root of factory hierarchy
》》》調用ApplicationContextAware接口setApplicationContext方法:org.springframework.context.support.ClassPathXmlApplicationContext@406c9125: startup date [Sun Mar 19 17:06:19 CST 2017]; root of context hierarchy
後置處理器處理bean=【beanLifecycle】開始
》》》註解初始化方法被調用
》》》BeanLifecycle調用了InitailizingBean的afterPorpertiesSet方法了.....
》》》init方法被調用
後置處理器處理bean=【beanLifecycle】完畢!
後置處理器處理bean=【test】開始
後置處理器處理bean=【test】完畢!
》》》Spring ApplicationContext容器初始化完畢了......
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0
beanLifecycle
postProcessor
test

從輸出信息看到:beanLifecycle被容器建立了。

相關文章
相關標籤/搜索