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进行了处理:

  1. finishBeanFactoryInitialization(beanFactory);

跟踪下去可以找到真正的读取lazy-init属性进行懒加载相关处理的地方

  1. 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的更多相关文章

  1. 死磕Spring之IoC篇 - @Autowired 等注解的实现原理

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...

  2. 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 ...

  3. 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 ...

  4. Spring - IoC(9): @Resoure & @Autowired

    @Resource 和 @Autowired 都是用来装配依赖的,它们之间有些异同. @Resoure @Resource 是 JSR-250 规范的注解. @Resource 可以标注在字段.方法上 ...

  5. Spring自动装配----注解装配----Spring自带的@Autowired注解

    Spring自动装配----注解装配----Spring自带的@Autowired注解 父类 package cn.ychx; public interface Person { public voi ...

  6. Spring Boot + Netty 中 @Autowired, @Value 为空解决

    问题描述 使用 Spring Boot + Netty 新建项目时 Handler 中的 @Autowired, @Value 注解的始终为空值 解决方法 @Component // 1. 添加 @C ...

  7. Spring注解@Resource和@Autowired区别对比

    转载:http://www.cnblogs.com/think-in-java/p/5474740.html @Resource和@Autowired都是做bean的注入时使用,其实@Resource ...

  8. Spring 注解 @Resource和@Autowired(转)

    鸣谢:http://my.oschina.net/u/216467/blog/205951 @Resource和@Autowired两者都是做bean的注入使用. 其实@Resource并不是Spri ...

  9. Spring注解 @Resource和@Autowired

    @Resource和@Autowired两者都是做bean的注入使用.其实@Resource并不是Spring的注解,他的包是javax.annotation.Resource 需要导入.但是Spri ...

  10. 使用Spring的JavaConfig 和 @Autowired注解与自动装配

    1 JavaConfig  配置方法 之前我们都是在xml文件中定义bean的,比如: 1 2 3 4 5 6 7 8 <beans xmlns="http://www.springf ...

随机推荐

  1. regasm 无法定位输入程序集

    c# 写的DLL是32位的,在64位机器上注册时提示 无法定位输入程序集 方法1: 使用绝对路径: "%windir%\Microsoft.NET\Framework\v2.0.50727\ ...

  2. Windows Azure Virtual Machine (35) Azure VM通过Linked DB,执行SQL Job

    <Windows Azure Platform 系列文章目录> 今天遇到一个Case,客户在使用Azure Automation,执行Azure SQL Database 存储过程的时候, ...

  3. ALGO-14_蓝桥杯_算法训练_回文数

    问题描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数 ...

  4. awk中使用shell的环境变量

    awk中使用shell的环境变量一:"'$var'"这种写法大家无需改变用'括起awk程序的习惯,是老外常用的写法.如:var="test"awk 'BEGIN ...

  5. C++标准模板库(STL)介绍:set的基本用法

    1.元素的方向遍历 使用反向迭代器reverse_iterator可以反向遍历集合,输出集合元素的反向排序结果.它需要用到rbegin()和rend()两个方法,它们分别给出了反向遍历的开始位置和结束 ...

  6. 阿里云服务器 ECS Linux SWAP 配置概要说明

    SWAP 简介 Linux 中的 SWAP(交换分区),类似于 Windows 的虚拟内存.系统会把一部分硬盘空间虚拟成内存使用,将系统内非活动内存换页到 SWAP,以提高系统可用内存. 注:参阅 E ...

  7. CentOS搭建SVN服务器,并通过Apache HTTP方式访问

    摘要:本文主要讲述了在centos 6.5环境下搭建svn服务器,可通过svn:\\IP方式访问.同时由于部分公司内网端口限制,并不能访问外网的svn服务器,所以特地结合了apache服务器,使得可以 ...

  8. python基础介绍

    一. 1.计算机基础 cpu:运算和控制:速度:飞机 内存:临时存储,供给cup数据,断电数据清空.成本高,速度:高铁 硬盘:相当于电脑的数据库,存储大量数据,数据永久保存(除非物理结构被破坏).速度 ...

  9. dialog--not attached to window manager

    该异常表示view没有添加到窗口管理器,通常是我们dismiss对话框的时候,activity已经不存在了,建议不要在非UI线程操作对话框. [解决方案]:常发生这类Exception的情形都是,有一 ...

  10. CNN卷积层:ReLU函数

    卷积层的非线性部分 一.ReLU定义 ReLU:全称 Rectified Linear Units)激活函数 定义 def relu(x): return x if x >0 else 0 #S ...