spring 之 lazy-init Autowired depends-on
1 lazy-init
lazy-init是延迟初始化的意思。
spring中容器都是尽早的创建和配置所有的单例bean,因此当容器在启动时,就会去配置和创建单例bean。 默认情况下 beans 的lazy-init 是没有配置的,就相当于是:
default-lazy-init="false"
bean 的 lazy-init 默认继承于 beans 的配置。 也就是说, 不配置任何lazy-init 的情况下: lazy-init = false
这样做的好处是在程序刚运行时就可以将配置的错误或者环境问题立刻暴露出来。当然,坏处就是启动时,因为要初始化所有的单例bean,系统开销会很大,启动过程比较慢。
如果不想单例bean提前实例化,可以设置lazy-initialized延迟加载,只有在第一次请求的时候采取初始化,而不是在启动容器时初始化。
如果一个非延迟的单例bean依赖了标记了lazy-init的bean,那么这个标记了lazy-init的bean也会在容器启动时被创建(延迟初始化失效)。
设置为延迟加载的bean一旦注入给不延迟的单例bean,就意味着它并不会被延迟加载了。
可以看到代码中对所有注册的bean,即this.beanDefinitionNames,对于每个bean都会做如下判断,如果成立就会执行依赖注入:
容器的初始化是在AbstractApplicationContext的refresh()方法中执行的,如下代码对lazy-init进行了处理:
- finishBeanFactoryInitialization(beanFactory);
跟踪下去可以找到真正的读取lazy-init属性进行懒加载相关处理的地方
- if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
可以看出,只有单例的bean才有可能在容器初始化的时候就完成依赖注入,当lazy-init属性不配置(默认值)或者配置为false的时候,上述if就会成立,当然这里默认不配置abstract属性,所以它默认也是false。if成立,就会执行getBean从而进行依赖注入,这样在容器初始化的过程中就已经实例化了Bean,当真正的请求bean的时候,其实只是从缓存中读取而已。
而如果lazy-init属性配置为true,那么就会进行懒加载了,这样在容器初始化的过程中不会进行依赖注入,只有当第一个getBean的时候才会实例化Bean。
2 lazy-init & depends-on
<!-- 移除 boss Bean 的属性注入配置的信息 -->
<bean id="boss" class="com.baobaotao.Boss" lazy-init="true"/> <!-- depends-on 测试 ,去掉 lazy-init配置后,也就是设置为 fasle, 那么 -->
<bean id="man" class="com.baobaotao.Man" depends-on="boss" lazy-init="true"/>
depends-on 是表明一种初始化的先后顺序,它 和 直接 直接的属性依赖(比如 Man 拥有一个 boss 属性)还是不一样的。 但是表现是差不多的。
具体来说, 就上面的例子, 如果 man 是延迟初始化的, 那么 boss 是否延迟初始化的都不要紧。 但是 如果 mans 是立即初始化的,那么 boss 也会立即被要求初始化, 即使 boss 设置了 lazy-init="true"。 如果boss 无法autowire 某些属性,那么容器就会抛出异常, man也就无法再完成初始化了!
为什么会这样呢? 观察源码可见:
AbstractBeanFactory.doGetBean 方法:
final RootBeanDefinition ex1 = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(ex1, beanName, args);
String[] dependsOn = ex1.getDependsOn();
String[] scopeName;
if(dependsOn != null) { // 这里开始对 bean 所依赖的其他bean 进行处理
scopeName = dependsOn;
int scope = dependsOn.length; for(int ex2 = ; ex2 < scope; ++ex2) {
String dep = scopeName[ex2];
if(this.isDependent(beanName, dep)) {
throw new BeanCreationException(ex1.getResourceDescription(), beanName, "Circular depends-on relationship between \'" + beanName + "\' and \'" + dep + "\'");
} this.registerDependentBean(dep, beanName);
this.getBean(dep);
}
}
另外, 从异常堆栈中, 可见其中存在getBean 和 doGetBean 方法的反复的相互调用,而这个正是 spring 在处理 depends-on 依赖:
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:) 这里出现了反复相互调用
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:)
3 lazy-init & Autowired 注解
lazy-init 和 Autowired 其实并没有明确的关系。 autowired 负责注入, 而lazy-init 关系到 初始化。 仅有的一点关系是: autowired 注入的 bean 必须是已经初始化成功了的bean。 换句话说, autowired 就相当于调用了 getBean,那么不管lazy-init如何设置, 被autowire需要的被依赖的那个bean 必须初始化。
如果一个bean 需要autowire 注入 另一个无法的bean,那么但是,这个bean 不要求立即初始化, 那么这个autowire 潜在的错误是不会暴露出来的。 也就是说, 推迟了可能出现的异常。
参考:
http://blog.csdn.net/qq30211478/article/details/77847677?locationNum=4&fps=1
http://blog.csdn.net/u011734144/article/details/72632327?locationNum=8&fps=1 : Spring源码分析之lazy-init属性的配置
lazy-init 有3个选项, true, false, default
spring 之 lazy-init Autowired depends-on的更多相关文章
- 死磕Spring之IoC篇 - @Autowired 等注解的实现原理
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...
- Spring Injection with @Resource, @Autowired and @Inject
August 1st, 2011 by David Kessler Overview I’ve been asked several times to explain the difference b ...
- Spring Auto-Wiring Beans with @Autowired annotation
In last Spring auto-wiring in XML example, it will autowired the matched property of any bean in cur ...
- Spring - IoC(9): @Resoure & @Autowired
@Resource 和 @Autowired 都是用来装配依赖的,它们之间有些异同. @Resoure @Resource 是 JSR-250 规范的注解. @Resource 可以标注在字段.方法上 ...
- Spring自动装配----注解装配----Spring自带的@Autowired注解
Spring自动装配----注解装配----Spring自带的@Autowired注解 父类 package cn.ychx; public interface Person { public voi ...
- Spring Boot + Netty 中 @Autowired, @Value 为空解决
问题描述 使用 Spring Boot + Netty 新建项目时 Handler 中的 @Autowired, @Value 注解的始终为空值 解决方法 @Component // 1. 添加 @C ...
- Spring注解@Resource和@Autowired区别对比
转载:http://www.cnblogs.com/think-in-java/p/5474740.html @Resource和@Autowired都是做bean的注入时使用,其实@Resource ...
- Spring 注解 @Resource和@Autowired(转)
鸣谢:http://my.oschina.net/u/216467/blog/205951 @Resource和@Autowired两者都是做bean的注入使用. 其实@Resource并不是Spri ...
- Spring注解 @Resource和@Autowired
@Resource和@Autowired两者都是做bean的注入使用.其实@Resource并不是Spring的注解,他的包是javax.annotation.Resource 需要导入.但是Spri ...
- 使用Spring的JavaConfig 和 @Autowired注解与自动装配
1 JavaConfig 配置方法 之前我们都是在xml文件中定义bean的,比如: 1 2 3 4 5 6 7 8 <beans xmlns="http://www.springf ...
随机推荐
- NDK开发: 打印C代码的调试信息Log
1.引入头文件 #include <android/log.h> 2.修改Android.mk 在其中加入 LOCAL_LDLIBS+= -L$(SYSROOT)/usr/lib -llo ...
- 黄聪:Windows+PHP7+ImageMagick
需要Apache下才适用,Nginx没测试过~ Step1 把ImageMagick对应版本下载下来(ps: 我这里下载的是这个版本ImageMagick-6.9.3-7-vc14-x86.zip) ...
- C/C++基础--模板与泛型编程
模板参数 函数模板,编译器根据实参来为我们推断模板实参. 模板中可以定义非类型参数,表示一个值而非一个类型,这些值必须是常量表达式,从而允许编译器在编译时实例化模板. 非类型参数可以是整型,或者一个指 ...
- 将字符串表示的IP地址转变为整形表示
当时面试上机的想法是,直接使用uint32_t变量来存ip地址,遍历字符串带".",然后去值,利用移位来将这个值填到uint32_t对应的位置上.这样的麻烦之处在于: 1,遍历字符 ...
- 关于Eclipse无法显示package Explorer 内容的解决方法
今天电脑不知道怎么搞的抽风了, package explorer等内容完全无法显示.用window->view方法手动添加还是setpreView都没有办法解决. 网上搜了半天也没有解决办法.无 ...
- 【ZZ】号称“开发者神器”的GitHub,到底该怎么用?
号称“开发者神器”的GitHub,到底该怎么用? https://mp.weixin.qq.com/s/zpKOBMKWckY05Mv_B28RgQ A developer’s introductio ...
- 如何进行CodeReview
一.代码规范的要点 代码规范主要分为风格规范与设计规范两大类: 1.代码风格规范 主要是文字上的规定,看似表面文章,实际上非常重要. 具体有如下几个方面: (1)缩进 (2)行宽 (3)断行/空白行 ...
- STP RSTP
一.透明网桥 1.对于一般的透明网桥来说,通常都具有以下的特点: +拓展LAN的能力 +自主动态学习站点的地址信息 当网桥的某个端口上收到含有某个源MAC地址的数据帧时,它就把该MAC地址和接收该数据 ...
- Jmeter(十五)Logic Controllers 之 while Controller
while Controller是控制循环的Controller,条件判断的Controller.先看看官方Demo. while Controller控制它的子对象,直到false为止.并且还提供了 ...
- [UE4]创建动画的3中方法
一.基于现有动画的骨骼,从头开始创建一个全新的动画.(不推荐) 选中左边的骨骼节点做旋转变化. 调整完成了别忘记点击添加“Key”以创建一个关键帧,然后再保存. 二.基于当前动画的姿势创建一个动画.( ...