Spring-- IOC容器详解(转)
Spring作为一个在java界广泛使用且评价颇高的一个开源框架,给我们提供了好多的功能,极大的方便了我们的开发。此处我介绍IOC容器和AOP概念。
IOC(Inversion of Control)控制反转:本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,这就叫控制反转,即交给了IOC容器,Spring的IOC容器主要使用DI方式实现的。不需要主动查找,对象的查找、定位和创建全部由容器管理。
通俗点说就是不创建对象。以前我们要调用一个对象的方法,首先要new一个对象。但使用IOC容器,在代码中不直接与对象连接,而是在配置文件中描述要使用哪一个对象。容器负责将这些联系在一起。
IOC容器的对象实例化是通过配置文件来实现的。术语上这叫做注入。注入有两种形式,采用构造方法注入和采用setter注入。具体的注入形式如下
采用set方法注入,给属性添加一个set方法,并对其进行赋值
publicclass UserManagerImplimplements UserManager {
private UserDaouserDao;
publicvoid setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
采用构造方法注入,在构造方法中对属性进行赋值
publicclass UserManagerImplimplements UserManager {
private UserDaouserDao;
public UserManagerImpl(UserDao userDao) {
this.userDao = userDao;
}
}
配置文件:
<beanid="userManager"align="left"> 对于依赖关系无须变化的Bean,构造注入更有用处;因为没有setter方法,所有的依赖关系全部在构造器内设定,因此,不用担心后续代码对依赖关系的破坏。
依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更符合高内聚的原则;
建议采用以设置注入为主,构造注入为辅的注入策略。对于依赖关系无须变化的注入,尽量采用构造注入;而其他的依赖关系的注入,则考虑采用设置注入。
此处我们说的普通属性的注入,但是还有一些列表,数组,map等类型的变量。我们看一下他们的注入形式:
01
<bean id="bean1" value="Hello_Spring"/>
03
04
<!--
05
<property name="intValue" value="123"/>
06
-->
07
<property name="intValue">
08
<value>123</value>
09
</property>
10
11
<property name="listValue">
12
<list>
13
<value>list1</value>
14
<value>list2</value>
15
</list>
16
</property>
17
<property name="setValue">
18
<set>
19
<value>set1</value>
20
<value>set2</value>
21
</set>
22
</property>
23
<property name="arrayValue">
24
<list>
25
<value>array1</value>
26
<value>array2</value>
27
</list>
28
</property>
29
<property name="mapValue">
30
<map>
31
<entry key="k1" value="v1"/>
32
<entry key="k2" value="v2"/>
33
</map>
34
</property>
35
<property name="dateValue" value="2009年12月14日" />
36
</bean>
spring中并不是所有类型的编辑器都实现好了,有些类型比如时间他就没有实现。需要我们自己去定义。如何自定义属性编辑器呢?首先,要继承 PropertyEditorSupport类,然后覆盖setAsText()方法,最后将自定义的属性编辑器注入到spring中
01
public class UtilDatePropertyEditorextends PropertyEditorSupport {
02
03
private Stringpattern;
04
05
@Override
06
07
publicvoid setAsText(String text)throws IllegalArgumentException {
08
09
System.out.println("---UtilDatePropertyEditor.setAsText()--->" + text);
10
11
try {
12
13
Date date = new SimpleDateFormat(pattern).parse(text);
14
15
this.setValue(date);
16
17
} catch (ParseException e) {
18
19
e.printStackTrace();
20
21
thrownew IllegalArgumentException(text);
22
23
}
24
25
}
26
27
publicvoid setPattern(String pattern) {
28
29
this.pattern = pattern;
30
31
}
32
33
}
这里pattern匹配形式,我们采用的是set注入。配置文件中实现为:
01
<bean id="customEditors" value="yyyy年MM月dd日"/>
07
</bean>
08
</entry>
09
</map>
10
</property>
11
</bean>
从上面可以看出,配置文件中每一个类用bean标签来标识,属性用property来标识。如果属性多的话,配置文件也会很繁杂。有没有某种情况能够减少配置文件的一些设置呢?确实是可以的,如果几个bean都有相同的属性,那这些属性是可以抽象出来的。比如:
01
<bean id="AbstractBean"abstract="true">
02
<propertyname="id"value="100"/>
03
<propertyname="name"value="zhangsan"/>
04
<propertyname="sex"value="nan"/>
05
</bean>
06
<beanid="bean3"
03
>
04
05
<!--
06
<bean id="bean2" ref="bean3"/>
08
<property name="bean4">
09
<ref bean="bean4"/>
10
</property>
11
<property name="bean5" ref="bean5"/>
12
</bean>
13
-->
14
15
<bean id="bean2"
03
>
04
05
<!--
06
<bean id="bean2" ref="bean3"/>
08
<property name="bean4">
09
<ref bean="bean4"/>
10
</property>
11
<property name="bean5" ref="bean5"/>
12
</bean>
13
-->
14
15
<bean id="bean2" value="100"/>
19
<property name="name" value="zhangsan"/>
20
<property name="sex" value="nan"/>
21
</bean>
IOC容器实现的bean配置与我们在代码中new实例达到的效果是一样的。那我们实例化的时候,可以采用单例模式,只保证有一个实例在运行,也可以多个实例运行。IOC容器中有这种配置吗?当然有,那就是bean的scope作用域。singleton默认值,每次调用getBean()向IOC容器中取得的对象是相同的。即单例。而prototype,则是每次调用getBean()向IOC容器中取得对象是不相同的。即相当于普通的实例化。
<bean id="bean1"class="com.bjpowernode.spring.Bean1"scope="prototype"/>
或者
<bean id="bean1"class="com.bjpowernode.spring.Bean1"scope="singleton"/>
通过IOC控制反转,大量减少了Factory和Singleton的数量,使代码层次更加清晰。Spring的IOC容器是一个轻量级的容器,没有侵入性,不需要依赖容器的API,也不需要实现一些特殊接口。而一个合理的设计最好尽量避免侵入性。减少了代码中的耦合,将耦合推迟到了配置文件中,发生了变化也更容易控制。
地址:http://www.open-open.com/lib/view/open1338175365089.html