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被容器建立了。