您的位置:首页 > 编程语言 > Java开发

Spring依赖注入

2015-08-12 14:22 567 查看
Bean配置信息是Bean的元数据信息,它由4个方面组成:Bean的实现类、Bean的属性信息、Bean的依赖关系和Bean的行为配置。
Bean元数据信息在Spring容器中的内部对应是由一个个BeanDefinition形成的Bean注册表,Spring实现了Bean元数据信息内部表示和外部表示的解耦。Spring支持多种形式Bean的配置方式。Bean配置信息定义了Bean的实现及依赖关系,Sprign容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后讲这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。

基于XML的配置
采用基于Schema配置格式,文件头的声明会复杂一些。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> </beans>

Schema在文档根节点中通过xmlns对文档中的命名空间进行声明。我们在上面的代码中定义了3个命名空间:
1.默认命名空间:没有空间名,用于Spring Bean的定义
2.xsi命名空间:这个命名空间用于为每个文档中命名空间指定相应的Schema样式文件,是标准组织定义的标准命名空间
3.aop命名空间:这个命名空间是Spring配置AOP的命名空间,是用户自定义的命名空间
命名空间的定义分为两个步骤:第一步指定命名空间的名称,第二步指定命名空间的Schema文档样式文件的位置,用空格或回车换行进行分隔

若命名空间的别名为空,则表示该命名空间为文档默认命名空间,文档中无命名空间前缀的元素都属于默认命名空间。
命名空间使用全限定名,每个组织机构在发布Schema文件后,都会为该Schema文件提供一个引用的URL地址,一般使用这个URL地址指定命名空间对应的Schema文件。命名空间名称和对应的Schema文件地址之间使用空格或回车分隔,不同的命名空间之间也使用这种分隔方法。

Bean的命名:在配置一个Bean时,需要为其指定一个id属性作为Bean的名称。id在IoC容器中必须是唯一的,此外id的命名需要满足XML对id的命名规范:必须以字母开始、后面可以是字母、数字、连字符、下划线、句号、冒号等完整结束符,逗号和空格这些非完整结束符是非法的。
Spring配置文件不允许出现两个相同id的<bean>,但却可以出现两个相同name的<bean>,若出现多个相同name的<bean>,通过getBean(beanName)时,返回最后声明的那个Bean。

属性注入要求bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。若在类中显式定义了一个带参的构造函数,则需要同时提供一个默认的构造函数。Spring只会检查Bean中是否有对应的setter方法,只有Bean中是否有对应的属性变量则不做要求。

JavaBean关于属性命名的特殊规范:JavaBean的属性变量名都以小写字母起头,但也允许大写字母开头的属性变量名,但必须满足变量的前两个字母要么全大写,要么全小写。

使用构造函数注入的前提是Bean必须提供带参的构造函数。
//通过类型匹配参数
public class Car{
public Car(String brand,double price){
this.brand=brand;
this.price=price;
}
}
<bean id="car" class="com.Car">
<constructor-arg type="java.lang.String">
<value>CA72</value>
</construtor-arg>
<constructor-arg type="double">
<value>20000</value>
</construtor-arg>
</bean>

//通过索引匹配参数
public class Car{
public Car(String brand,String corp,double price){
this.brand=brand;
this.corp=corp;
this.price=price;
}
}
<bean id="car" class="com.Car">
<constructor-arg index="0" value="CA72" />
<constructor-arg index="1" value="CHINA" />
<constructor-arg index="2" value=20000 />
</bean>

//通过使用索引和类型匹配参数
public class Car{
public Car(String brand,String corp,double price){
this.brand=brand;
this.corp=corp;
this.price=price;
}
}
public class Car{
public Car(String brand,String corp,int price){
this.brand=brand;
this.corp=corp;
this.price=price;
}
}
<bean id="car" class="com.Car">
<constructor-arg index="0" type="java.lang.String">
<value>CA72</value>
</construtor-arg>
<constructor-arg index="1" type="java.lang.String">
<value>CHINA</value>
</construtor-arg>
<constructor-arg index="2" type="double">
<value>20000</value>
</construtor-arg>
</bean>

通过自身类型反射匹配入参:若Bean构造函数入参的类型是可辨别的,即使构造函数注入配置不提供类型和索引信息,Spring依旧可以正确地完成构造函数的注入工作。

XML共有5个特殊的字符,若配置文件中的注入值包括这些特殊字符,需要进行特别处理。
XML特殊实体符号
特殊符号 转义序列 特殊符号 转义序列
< < " "
> > ' &apos
& &

<ref>可以通过一下三个属性引用容器中其他Bean
bean:通过该属性可以引用同一容器或父容器的Bean
local:通过该属性只能引用同一配置文件中定义的Bean,它可以利用XML解析器自动检验引用的合法性,以便在开发编写配置时能够及时发现并纠正配置的错误。
parent:引用父容器中的Bean

Spring使用跟一个专用的<null/>元素标签作为null值。

<list>
<value></value>
<value></value>
</list>

<set>
<value></value>
<value></value>
</set>

<map>
<entry>
<key><value></value></key>
<value></value>
</entry>
<entry>
<key><value></value></key>
<value></value>
</entry>
</map>

<property>
<props>
<prop key=""></pro>
<prop key=""></pro>
</props>
</property>

集合合并:允许子<bean>继承父<bean>的同名属性集合元素,并将子<bean>中配置的结合属性值和父<bean>中配置的同名属性值合并起来作为最终的bean值。
<bean id="parentBoss" abstract-"true" class="Boss">
<property name="favorites">
<set>
<value>Read</value>
<value>Run</value>
</set>
</property>
</bean>
<bean id="childBoss" parent="parentBoss">
<property name="favorites">
<set merge="true">
<value>Swim</value>
<value>Sing</value>
</set>
</property>
</bean>

若需配置一个集合类型的Bean,为非一个集合类型的属性,可以通过util命名空间进行配置。
<util:list id="" list-class="">
<value>Swim</value>
<value>Sing</value>
</util:list>

为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息。
例:使用p明明空间
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="car" class=""
p:brand=""
p:maxSpeed=""
/>
</beans>

<bean>元素提供改了一个指定自动装配类型的属性:autowire="<自动装配类型>"。Spring提供了4种自动装配类型。
byName:根据名称进行自动匹配
byType:根据类型进行自动匹配
constructor:与ByType类似,只不是针对构造函数注入而言
autodetect:根据Bean的自省机制决定采用byType还是constructor进行自动装配

lookup方法注入
public interface MagicBoss{
Car getCar();
}

<bean id="car" class="Car"
p:brand=""
p:price=""
scope="prototype"
/>
<bean id="magicBoss" class="MagicBoss">
<lookup-method name="getCar" bean="car" />
</bean>

方法替换
用于替换他人的bean必须实现MethodReplacer接口,Spring将利用该接口方法去替换目标Bean的方法。
public class Boss1{
public Car getCar(){
Car car = new Car();
car.setBrand("BMWZ4");
return car;
}
}

public class Boss2 implements MethodReplacer{
public Object reimplement(Object arg0,Method arg1,Object[] arg2) throws Throwable{
Car car = new Car();
car.setBrand("BENZ");
return car;
}
}

<bean id="boss1" class="Boss1">
<replace-method name="getCar" replacer="boss2" />
</bean>
<bean id="boss2" class="Boss2" />

bean之间的关系有继承、依赖和引用。
继承:父<bean>的主要功能是简化子<bean>的配置。一般都将父<bean>设为abstract类,表示为这个<bean>不实例化为对应的Bean。
<bean id="abstractCar" class="Car"
p:brand="BMWZ4"
p:maxSpeed=250
abstract="true"
/>
<bean id="Car1" parent="abstractCar" p:color="red" />
<bean id="Car2" parent="abstractCar" p:color="black" />

依赖:使用<ref>元素标签建立对其他bean的依赖关系,Spring负责管理这些Bean的关系,当实例化一个Bean时,Spring保证该Bean所依赖的其他Bean已经初始化。Spring允许用户通过depends-on属性指定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好。

public class SystemSettings{
public static int SESSION_TIMEOUT=30;
public static int REFRESH_CYCLE=60;
}

public class SysInit{
public SysInit(){
SystemSettings.SESSION_TIMEOUT=10;
SystemSettings.REFRESH_CYCLE=100;
}
}

public class CacheManager{
public CacheManager(){
Timer timer = new Timer();
TimerTash cacheTask = new CacheTask();
timer.schedule(cacheTask,0,SystemSettings.REFRESH?_CYCLE);
}
}

<bean id="manager" class="CacheManager" depends-on="sysInit" />
<bean id="sysInit" class="SysInit" />

引用:Spring提供了一个<idref>标签,通过<idref>引用跟另一个<bean>的名字
<bean id="car" class="Car">
<bean id="boss" class="Boss">
<property name="carId">
<idref bean="car" />
</property>
</bean>

整合多个配置文件:Spring允许我们通过<import>将多个配置文件引入到一个文件中,进行配置文件的集成。
<import resource="classpath:com/beans1.xml">

Bean的作用域类型
类别 说明
singleton 在Sprign IoC容器中仅存在一个Bean实例,Bean以单实例的方式存在
prototype 每次从容器中调用Bean时,都返回一个新的实例
request 每次HTTP Session请求都会创建一个新的Bean,仅适用于WebApplicationContxt环境
session 同一个HTTP Session共享一个Bean,不同HTTP Session使用不同的Bean,仅适用于WebApplicationContxt环境
globalSession 同一个全局Session共享一个Bean,一般用于porlet应用环境,仅适用于WebApplicationContxt环境

Spring还允许用户自定义Bean的作用域,可以通过org.springframework.beans.factory.config.Scope接口定义新的作用域,再通过org.springframeworl.beans.factory.config.CustomScopeConfigure总金额个BeanFactoryPostProcessor注册自定义的Bean作用域。

singleton作用域
无状态或状态不可变的类适合使用单实例模式。在Spring环境下,对于所有的Dao类都可以采用单实例模式。在默认情况下,Spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存于容器中。虽然在启动时会花费一些时间,但带来两个好处:首先对Bean提前的实例化操作会及早发现一些潜在的配置问题;其次Bean以缓存的方式保存,当运行期使用到该Bean时就无须再实例化了,加快了运行效率。若用户不希望在容器启动时提前实例化singleton的Bean,可以通过lazy-init属性进行控制:
<bean id="boss1" class="Boss" lazy-init="true" />

prototype作用域:采用scope="prototype"指定非单实例作用域的Bean。在默认的情况下,Spring容器在启动时不实例化prototype的Bean。此外,Spring容器将prototype的Bean交给调用者,就不再管理它的生命周期了。

Web应用环境相关的Bean作用域
若用户使用Spring的WebApplicationContext,则还可使用另外3种Bean的作用域:request、session和globalSession。不过使用这些作用域之前,首先必须在Web容器中进行一些额外的配置。
在Web容器中进行额外的配置
在低版本的Web容器中,用户可以使用HTTP请求过滤器进行配置
<web-app>
...
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
在高版本的Web容器中,则可以利用HTTP请求监听器进行配置
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: