spring基础——DI(五)
在上几篇中学习了基本DI知识,本篇继续介绍更多关于DI的问题。
1、延迟初始化bean
延迟初始化也叫惰性初始化,指的是不提前初始化bean,而只有在真正使用时才创建及初始化。配置方式很简单只需要在bean标签上指定lazy-init属性为true时,即可延迟初始化bean。
2、使用depends-on
depends-on是指定bean初始化及销毁顺序,使用depends-on属性指定的bean需要先初始化完毕才能初始化当前bean。由于只有singleton的bean才能被spring管理销毁,所以当指定bean是singleton时,depends-on指定的bean要在当前bean之
后销毁。
1 <bean id="resourceBean" class="cn.javass.spring.chapter3.bean.ResourceBean" init-method="init" destroy-method="destroy"> 2 <property name="file" value="D:/test.txt"/> 3 </bean> 4 <bean id="dependentBean" class="cn.javass.spring.chapter3.bean.DependentBean" init-method="init" destroy-method="destroy" depends-on="resourceBean"> 5 <property name="resourceBean" ref="resourceBean"/> 6 </bean>
1 package cn.javass.spring.chapter3.bean; 2 import java.io.File; 3 import java.io.FileNotFoundException; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 public class ResourceBean { 7 private FileOutputStream fos; 8 private File file; 9 //初始化方法 10 public void init() { 11 System.out.println("ResourceBean:========初始化"); 12 //加载资源,在此只是演示 13 System.out.println("ResourceBean:========加载资源,执行一些预操作"); 14 try { 15 this.fos = new FileOutputStream(file); 16 } catch (FileNotFoundException e) { 17 e.printStackTrace(); 18 } 19 } 20 //销毁资源方法 21 public void destroy() { 22 System.out.println("ResourceBean:========销毁"); 23 //释放资源 24 System.out.println("ResourceBean:========释放资源,执行一些清理操作"); 25 try { 26 fos.close(); 27 } catch (IOException e) { 28 e.printStackTrace(); 29 } 30 } 31 public FileOutputStream getFos() { 32 return fos; 33 } 34 public void setFile(File file) { 35 this.file = file; 36 } 37 } 38 39 package cn.javass.spring.chapter3.bean; 40 import java.io.IOException; 41 public class DependentBean { 42 ResourceBean resourceBean; 43 public void write(String ss) throws IOException { 44 System.out.println("DependentBean:=======写资源"); 45 resourceBean.getFos().write(ss.getBytes()); 46 } 47 //初始化方法 48 public void init() throws IOException { 49 System.out.println("DependentBean:=======初始化"); 50 resourceBean.getFos().write("DependentBean:=======初始化=====".getBytes()); 51 } 52 //销毁方法 53 public void destroy() throws IOException { 54 System.out.println("DependentBean:=======销毁"); 55 //在销毁之前需要往文件中写销毁内容 56 resourceBean.getFos().write("DependentBean:=======销毁=====".getBytes()); 57 } 58 59 public void setResourceBean(ResourceBean resourceBean) { 60 this.resourceBean = resourceBean; 61 } 62 } 63 64 package cn.javass.spring.chapter3; 65 import java.io.IOException; 66 import org.junit.Test; 67 import org.springframework.context.support.ClassPathXmlApplicationContext; 68 import cn.javass.spring.chapter3.bean.DependentBean; 69 public class MoreDependencyInjectTest { 70 @Test 71 public void testDependOn() throws IOException { 72 ClassPathXmlApplicationContext context = 73 new ClassPathXmlApplicationContext("chapter3/depends-on.xml"); 74 //一点要注册销毁回调,否则我们定义的销毁方法不执行 75 context.registerShutdownHook(); 76 DependentBean dependentBean = 77 context.getBean("dependentBean", DependentBean.class); 78 dependentBean.write("aaa"); 79 } 80 }
3、自动装配
自动装配就是指由spring来自动注入依赖对象,无需人工参与。目前spring3.0支持no 、byName、byType、constructor四种自动装配。自动装配的好处是减少构造器注入和setter注入配置,减少配置文件长度。自动装配通过配置
bean标签的autowrie属性来改变自动装配方式。
default:表示使用默认的自动装配,默认的自动装配需要在beans标签中使用default-autowire属性指定,其支持no 、byName、byType、constructor。
no:意思是不支持自动装配,必须明确指定依赖。
byName:通过设置bean标签定义属性autowire=“byName”,意思是根据名字进行自动装配,只能用于setter注入。
byType:通过设置bean标签定义属性autowire=“byType”,意思是根据类型进行自动装配,同样用于setter注入。根据类型找到多个bean时,对于集合类型将注入所有匹配的候选者,而对于其他非集合类型则需要使用autowire-candidate属性
为false来放弃作为自动装配的候选者。或者使用primary属性为true来指定某个bean为首选bean。
1 <!--根据名称自动装配--> 2 <bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 3 <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" 4 autowire="byName"/> 5 <!--根据类型自动装配--> 6 <bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 7 <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" 8 autowire="byType"/>
1 <bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 2 <!-- 从自动装配候选者中去除 --> 3 <bean class="cn.javass.spring.chapter2.helloworld.HelloImpl" 4 autowire-candidate="false"/> 5 <bean id="bean1" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" 6 autowire="byType"/> 7 8 <bean class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 9 <!-- 自动装配候选者中的首选Bean--> 10 <bean class="cn.javass.spring.chapter2.helloworld.HelloImpl" primary="true"/> 11 <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" 12 autowire="byType"/>
constructor:通过设置bean属性autowire=“constructor”,功能和byType功能一样,根据类型注入构造器参数,只是用于构造器注入方式。
注:1、不论是根据名字还是根据类型注入,都将排除当前bean。
2、不是所有类型都能自动装配。不能自动装配的数据类型有Object,基本数据类型;通过beans标签default-autowire-candidates属性指定匹配模式,不匹配的将不能作为自动装配的候选者。
3、数组,集合,字典类型根据类型自动装配和普通类型的自动装配是由却别的。数组类型,集合(Set,List,Collection)接口类型,字典接口类型将根据泛型获取匹配的所有候选者注入到数组或集合中,而对于集合的具体类型将只选择一个候选者。
如List<T> list将选择所有T类型的bean注入到list中,而ArrayList<T> list将选择一个类型为ArrayList的bean注入,字典类型同理。
4、配置注入的数据会自动覆盖自动装配注入的数据。
4、依赖检查
用于检查bean定义的属性都注入数据了,不管是自动装配的还是配置方式注入的都能检查,如果没有注入数据将报错。
none:默认检查方式,不检查。
objects:检查除基本类型外的依赖对象,基本数据类型属性为null也不会报错,配置方式为:
1 <bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 2 <!-- 注意我们没有注入helloApi,所以测试时会报错 --> 3 <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="objects"> 4 <property name="message" value="Haha"/> 5 </bean>
simple:对基本类型进行依赖检查,包括数组类型,其他依赖不报错
1 <bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 2 <!-- 注意我们没有注入message属性,所以测试时会报错 --> 3 <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="simple"> 4 <property name="helloApi" ref="helloApi"/> 5 </bean>
all:对以上所有类型进行依赖检查
1 <bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/> 2 <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" dependency-check="all"> 3 <property name="helloApi" ref="helloApi"/> 4 <property name="message" value="Haha"/> 5 </bean>
依赖检查也可以通过beans标签中的default-dependcy-check属性来指定全局依赖检查配置。