DI 之 3.3 更多DI的知识(陆)
3.3.1 延迟初始化Bean
延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean。
配置方式很简单只需在<bean>标签上指定 “lazy-init” 属性值为“true”即可延迟初始化Bean。
Spring容器会在创建容器时提前初始化“singleton”作用域的Bean,“singleton”就是单例的意思即整个容器每个Bean只有一个实例,后边会详细介绍。Spring容器预先初始化Bean通常能帮助我们提前发现配置错误,所以如果没有什么情况建议开启,除非有某个Bean可能需要加载很大资源,而且很可能在整个应用程序生命周期中很可能使用不到,可以设置为延迟初始化。
延迟初始化的Bean通常会在第一次使用时被初始化;或者在被非延迟初始化Bean作为依赖对象注入时在会随着初始化该Bean时被初始化,因为在这时使用了延迟初始化Bean。
容器管理初始化Bean消除了编程实现延迟初始化,完全由容器控制,只需在需要延迟初始化的Bean定义上配置即可,比编程方式更简单,而且是无侵入代码的。
具体配置如下:
<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl" lazy-init="true"/>
3.3.2 使用depends-on
depends-on是指指定Bean初始化及销毁时的顺序,使用depends-on属性指定的Bean要先初始化完毕后才初始化当前Bean,由于只有“singleton”Bean能被Spring管理销毁,所以当指定的Bean都是“singleton”时,使用depends-on属性指定的Bean要在指定的Bean之后销毁。
配置方式如下:
<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
<bean id="decorator" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" depends-on="helloApi">
<property name="helloApi"><ref bean="helloApi"/></property>
</bean>
“decorator”指定了“depends-on”属性为“helloApi”,所以在“decorator”Bean初始化之前要先初始化“helloApi”,而在销毁“helloApi”之前先要销毁“decorator”,大家注意一下销毁顺序,与文档上的不符。
“depends-on”属性可以指定多个Bean,若指定多个Bean可以用“;”、“,”、空格分割。
那“depends-on”有什么好处呢?主要是给出明确的初始化及销毁顺序,比如要初始化“decorator”时要确保“helloApi”Bean的资源准备好了,否则使用“decorator”时会看不到准备的资源;而在销毁时要先在“decorator”Bean的把对“helloApi”资源的引用释放掉才能销毁“helloApi”,否则可能销毁 “helloApi”时而“decorator”还保持着资源访问,造成资源不能释放或释放错误。
让我们看个例子吧,在平常开发中我们可能需要访问文件系统,而文件打开、关闭是必须配对的,不能打开后不关闭,从而造成其他程序不能访问该文件。让我们来看具体配置吧:
1)准备测试类:
ResourceBean从配置文件中配置文件位置,然后定义初始化方法init中打开指定的文件,然后获取文件流;最后定义销毁方法destroy用于在应用程序关闭时调用该方法关闭掉文件流。
DependentBean中会注入ResourceBean,并从ResourceBean中获取文件流写入内容;定义初始化方法init用来定义一些初始化操作并向文件中输出文件头信息;最后定义销毁方法用于在关闭应用程序时想文件中输出文件尾信息。
具体代码如下:
package cn.javass.spring.chapter3.bean;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ResourceBean {
private FileOutputStream fos;
private File file;
//初始化方法
public void init() {
System.out.println("ResourceBean:========初始化");
//加载资源,在此只是演示
System.out.println("ResourceBean:========加载资源,执行一些预操作");
try {
this.fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//销毁资源方法
public void destroy() {
System.out.println("ResourceBean:========销毁");
//释放资源
System.out.println("ResourceBean:========释放资源,执行一些清理操作");
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public FileOutputStream getFos() {
return fos;
}
public void setFile(File file) {
this.file = file;
}
}
package cn.javass.spring.chapter3.bean;
import java.io.IOException;
public class DependentBean {
ResourceBean resourceBean;
public void write(String ss) throws IOException {
System.out.println("DependentBean:=======写资源");
resourceBean.getFos().write(ss.getBytes());
}
//初始化方法
public void init() throws IOException {
System.out.println("DependentBean:=======初始化");
resourceBean.getFos().write("DependentBean:=======初始化=====".getBytes());
}
//销毁方法
public void destroy() throws IOException {
System.out.println("DependentBean:=======销毁");
//在销毁之前需要往文件中写销毁内容
resourceBean.getFos().write("DependentBean:=======销毁=====".getBytes());
} public void setResourceBean(ResourceBean resourceBean) {
this.resourceBean = resourceBean;
}
}
2)类定义好了,让我们来进行Bean定义吧,具体配置文件如下:
<bean id="resourceBean" class="cn.javass.spring.chapter3.bean.ResourceBean"
init-method="init" destroy-method="destroy">
<property name="file" value="D:/test.txt"/>
</bean>
<bean id="dependentBean" class="cn.javass.spring.chapter3.bean.DependentBean"
init-method="init" destroy-method="destroy" depends-on="resourceBean">
<property name="resourceBean" ref="resourceBean"/>
</bean>
<property name="file" value="D:/test.txt"/>配置:Spring容器能自动把字符串转换为java.io.File。
init-method="init" :指定初始化方法,在构造器注入和setter注入完毕后执行。
destroy-method="destroy":指定销毁方法,只有“singleton”作用域能销毁,“prototype”作用域的一定不能,其他作用域不一定能;后边再介绍。
在此配置中,resourceBean初始化在dependentBean之前被初始化,resourceBean销毁会在dependentBean销毁之后执行。
3)配置完毕,测试一下吧:
package cn.javass.spring.chapter3;
import java.io.IOException;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.javass.spring.chapter3.bean.DependentBean;
public class MoreDependencyInjectTest {
@Test
public void testDependOn() throws IOException {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("chapter3/depends-on.xml");
//一点要注册销毁回调,否则我们定义的销毁方法不执行
context.registerShutdownHook();
DependentBean dependentBean =
context.getBean("dependentBean", DependentBean.class);
dependentBean.write("aaa");
}
}
测试跟其他测试完全一样,只是在此我们一定要注册销毁方法回调,否则销毁方法不会执行。
如果配置没问题会有如下输出:
ResourceBean:========初始化
ResourceBean:========加载资源,执行一些预操作
DependentBean:=========初始化
DependentBean:=========写资源
DependentBean:=========销毁
ResourceBean:========销毁
ResourceBean:========释放资源,执行一些清理操作
DI 之 3.3 更多DI的知识(陆)的更多相关文章
- DI 之 3.3 更多DI的知识(柒)
3.3.3 自动装配 3.3.4 依赖检查 3.3.5 方法注入
- 开涛spring3(3.3) - DI 之 3.3 更多DI的知识
3.3.1 延迟初始化Bean 延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean. 配置方式很简单只需在<bean>标签上指定 “lazy- ...
- [跟我学spring学习笔记][更多DI知识]
延迟初始化Bean 定义: 延迟初始化也叫做惰性初始化,指不提前初始化Bean,在真正使用时才创建并初始化Bean 如何延迟: 配置方式很简单只需在标签上指定 “lazy-init” 属性值为“tru ...
- 《转载》跟我学spring3
一.<跟我学spring3>电子书下载地址: <跟我学spring3> (1-7 和 8-13) http://jinnianshilongnian.iteye.com/bl ...
- 跟我学SpringMVC目录汇总贴、PDF下载、源码下载
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- Spring 使用介绍(二)—— IoC
一.简单使用:Hello World实例 1.maven添加依赖 <dependency> <groupId>org.springframework</groupId&g ...
- 《OD面试》Java面试题整理
一.面试考察点 1 主语言本身 2 数据库 3 算法 4 Spring/SpringMVC/MyBatis 5 项目经验 1)项目涉及到的技术点深挖: (1)考察候选人技术深度 (2)看候选人遇到问 ...
- IoC/DI
From:http://jinnianshilongnian.iteye.com/blog/1471944 我对IoC/DI的理解 博客分类: spring杂谈 IoCDI IoC IoC: Inv ...
- 我对IoC/DI的理解
IoC IoC: Inversion of Control,控制反转, 控制权从应用程序转移到框架(如IoC容器),是框架共有特性 1.为什么需要IoC容器 1.1.应用程序主动控制对象的实例化及依赖 ...
随机推荐
- 基于Node的PetShop,RESTful API以及认证
前篇 - 基本认证,用户名密码 后篇 - OAuth2 认证 由于宠物店的业务发展需要,我们需要一种更加便捷的方式来管理日益增多的宠物和客户.最好的方法就是开发一个APP,我可以用这个APP来添加.更 ...
- 【Java】List集合按数量分组
有时候,我们需要将大的集合按指定的数量分割成若干个小集合.(比如:集合作为SQL中IN的参数,而SQL又有长度限制,所以需要分批分几次进行查询) 虽然此需求感觉不常见,但偶也写过几次类似的方法,故记录 ...
- 【MySQL】MySQL的group_concat使用例子
> 参考的优秀文章 GROUP_CONCAT(expr) > 简单的例子 此函数的功能,是拼接group分组多行的数据为一行,并可以指定去重.排序.分隔符. 例子: select t.na ...
- Python3基础 random 产生置顶区间的随机整数
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- Shell 脚本面试问题大全
我们为你的面试准备选择了 70 个你可能遇到的 shell 脚本面试问题及解答.了解脚本或至少知道基础知识对系统管理员来说至关重要,它也有助于你在工作环境中自动完成很多任务.在过去的几年里,我们注意到 ...
- HTTP传送协议
HTTP传送协议--学习笔记 HTTP数据传输格式 基本格式为: 请求或应答行 请求或应答头部 空行 数据 POST传送格式 底层数据通信: 客户端请求: POST /response.php HTT ...
- uTenux-OS-Task再探
在第一节中我由于没有拿到开发板,所以被迫无奈,只能将uTenux操作系统移植到手中的一块STM32F103的开发板上,当时对于uTenux的理解还不够,只是看了一下文件架构和效果,虽然移植成功了,但是 ...
- 【leetcode❤python】118. Pascal's Triangle
#-*- coding: UTF-8 -*-#杨辉三角class Solution(object): def generate(self, numRows): "&quo ...
- BZOJ 1976 能量魔方 Cube(最小割)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1976 题意:给出一个n*n*n的立方体.每个小单位为字母P或者字母N.相邻两个小单位字母 ...
- Cheatsheet: 2014 07.01 ~ 07.31
Web Maximize Compression with Zopfli Browser Detection with JavaScript Simple MySQL Master HA with m ...