DI依赖注入
DI
DI—Dependency Injection,即“依赖注入”, 由容器动态的将某个依赖关系注入到组件之中。
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
依赖注入 明确描述了“被注入对象依赖IoC容器配置依赖对象”
Spring IoC容器的依赖有两层含义:Bean依赖容器和容器注入Bean的依赖资源
使用依赖注入,更好的增加Bean的可复用性,降低Bean之间的耦合,使得代码结构更清晰
依赖资源主要有以下两种基本实现方式:
构造器注入:就是容器实例化Bean时注入那些依赖,通过在在Bean定义中指定构造器参数进行注入依赖,包括实例工厂方法参数注入依赖,但静态工厂方法参数不允许注入依赖
setter注入:通过setter方法进行注入依赖;
方法注入:能通过配置方式替换掉Bean方法,也就是通过配置改变Bean方法 功能
1、构造器注入
①. 根据参数索引注入
其中“index”表示索引,从0开始,即第一个参数索引为0,“value”来指定注入的常量值
②. 根据参数类型进行注入
其中“type”表示需要匹配的参数类型,可以是基本类型也可以是其他类型,如“int”、“java.lang.String”,“value”来指定注入的常量值
③. 根据参数名进行注入
其中“name”表示需要匹配的参数名字,“value”来指定注入的常量值,
2、setter注入
在通过构造器、静态工厂或实例工厂实例好Bean后,通过调用Bean类的setter方法进行注入依赖,
setter注入的方法名要遵循“JavaBean getter/setter 方法命名约定:
setter方法,以“set” 开头,后跟首字母大写的属性名(驼峰命名方式)
getter方法,一般属性以“get”开头,对于boolean类型一般以“is”开头,后跟首字母大写的属性名,如“getMesssage”,“isOk”;
注:Spring类型转换系统对于boolean类型进行了容错处理,除了可以使用“true/false”标准的Java值进行注入,还能使用“yes/no”、“on/off”、“1/0”来代表“真/假
3、集合,数组和字典(Map)注入
(1)、List类型
(2)、Set类型
需要使用标签来配置注入,其配置参数及含义和标签完全一样
<bean id="setBean" class="…..">
<property name="values">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>
</bean>
(3)、数组类型
使用< array>标签来配置注入,其中标签属性“value-type”和“merge”和标签含义完全一样
(4)、Map字典类型
map>标签来配置注入,其属性“key-type”和“value-type”分别指定“键”和“值”的数据类型,其含义和< list>标签的“value-type”含义一样, 并使用< key>子标签来指定键数据,< value>子标签来指定键对应的值数据,
4、引用其他Bean
构造器标签里引用
属性标签中引用
命名空间
延迟初始化Bean
不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean。
在< bean>标签上指定 “lazy-init” 属性值为“true”即可延迟初始化Bean。
Spring容器会在创建容器时提前初始化“singleton”作用域的Bean,除非有某个Bean可能需要加载很大资源,而且很可能在整个应用程序生命周期中很可能使用不到,可以设置为延迟初始化。
<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"
lazy-init="true"/>
<!-- depends-on是指指定Bean初始化及销毁时的顺序 -->
<bean id="helloApi" class="com.feng.spring.chapter2.helloworld.HelloApi">
</bean>
<bean id="decorator"
class="cn.javass.spring.chapter3.bean.HelloApiDecorator"
depends-on="helloApi">
<property name="helloApi"><ref bean="helloApi"/></property>
</bean>
使用depends-on属性指定的Bean要先初始化完毕后才初始化当前Bean,由于只有”singleton”Bean才能被Spring管理销毁,所以当指定的Bean都是”singleton”时,使用depends-on属性指定的Bean要在指定的Bean之后销毁。所以初始化decorator之前需要先初始化HelloApi,销毁HelloApi之前需要先销毁decorator
< property name="file" value="D:/test.txt"/>
<!--
配置:Spring容器能自动把字符串转换为java.io.File
init-method=”init” :指定初始化方法,在构造器注入和setter注入完毕后执行。
destroy-method=”destroy”:指定销毁方法,只有“singleton”作用域能销毁,“prototype”作用域
的一定不能,
-->
自动装配
由Spring来自动地注入依赖对象,无需人工参与,
目前Spring3.0支持“no”、“byName ”、“byType”、“constructor”四种自动装配,推荐使用Java 5+支持的(@Autowired)注解方式代替
自动装配的好处是减少构造器注入和setter注入配置,减少配置文件的长度。自动装配通过配置< bean>标签的“autowire”属性来改变自动装配方式。
- byName:通过设置Bean定义属性autowire=”byName”, 意思是根据名字进行自动装配,
只能用于setter注入。
< bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator"
autowire="byName"/>
byType:通过设置Bean定义属性autowire=”byType”,意思是指根据类型注入,用于setter注入,
根据类型找到多个Bean时,使用“primary”属性为true来指定某个Bean为首选Beanconstructor:通过设置Bean定义属性autowire=”constructor”,功能和“byType”功能一样,根据类型注入构造器参数,只是用于构造器注入方式,
可以采用在“< beans>”标签中通过“default-autowire”属性指定全局的自动装配方式,即如果default-autowire=”byName”,将对所有Bean进行根据名字进行自动装配。
自动装配也是有缺点的,最重要的缺点就是没有了配置,在查找注入错误时非常麻烦,还有比如基本类型没法完成自动装配,所以可能经常发生一些莫名其妙的错误,在此推荐不要使用该方式,最好是指定明确的注入方式,或者采用最新的Java5+注解注入方式。
依赖检查
依赖检查:用于检查Bean定义的属性都注入数据了,不管是自动装配的还是配置方式注入的都能检查,如果没有注入数据将报错,从而提前发现注入错误,只检查具有setter方法的属性。
建议采用Java5+ @Required注解方式,
Bean的作用域
在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围。
Spring提供“singleton”和“prototype”两种基本作用域,
另外提供“request”、“session”、“global session”三种web作用域;
Singleton
在Spring容器中如果没指定作用域默认就是“singleton”,配置方式通过scope属性配置,
< bean class="cn.javass.spring.chapter3.bean.Printer" scope="singleton"/>
Spring不仅会缓存单例对象,Bean定义也是会缓存的,对于惰性初始化的对象是在首次使用时根据Bean定义创建并存放于单例缓存池。
Prototype
Prototype
原型,指每次向Spring容器请求获取Bean都返回一个全新的Bean,相对于“singleton”来说就是不缓存Bean,每次都是一个根据Bean定义创建的全新Bean。
<bean class="cn.javass.spring.chapter3.bean.Printer" scope="prototype"/>
Web应用中的作用域
三种Web作用域:request、session、globalSession
一、request作用域:表示每个请求需要容器创建一个全新Bean。比如提交表单的数据必须是对每次请求新建一个Bean来保持这些表单数据,请求结束释放这些数据
二、session作用域:表示每个会话需要容器创建一个全新Bean。比如对于每个用户一般会有一个会话,该用户的用户信息需要存储到会话中,此时可以将该Bean配置为web作用域。
三、globalSession:类似于session作用域,只是其用于portlet环境的web应用。如果在非portlet环境将视为session作用域。
Resource资源接口
Spring 提供一个Resource接口来统一这些底层资源一致的访问,而且提供了一些便利的接口,从而能提供我们的生产力。
Spring的Resource接口代表底层外部资源,提供了对底层外部资源的一致性访问接口。
Resource接口提供了足够的抽象,足够满足我们日常使用。而且提供了很多内置Resource实现:ByteArrayResource、 InputStreamResource 、FileSystemResource 、UrlResource 、ClassPathResource、ServletContextResource、VfsResource等