.1 如何获取 spring
登陆 http://www.springframework.org下载 spring 开发包。
快速应用 spring 核心 IOC 实例
Spring 的 IOC 容器讲解
控制反转 IoC(Inversion of Control) : ioc 是一种编程思想,主要是协调各组件间相互的依赖关系。 Ioc 就是由容器来控制业务对象之间的依赖关系,而非传统方式中由代码来直接操控,控制反转的本质,是控制权由应用代码转到了外部容器,控制权的转移即是所谓的反转,控制权的转移带来的好处就是降低了业务对象之间的依赖程度,即实现了解耦。
对象的创建一共有三种:自己创建,工厂模式创建,外部注入。对应三个动词: new , get , set
New --- 自己创建
Get --- 工厂模式
优点:实现了对象的统一创建,调用者无须关心对象创建的过程,只管从工厂中取得即可
Set--- 外部注入
Ioc 模式的优缺点
优点:
IOC 把对象放在了 XML 中定义,所以当我们需要换一个实现子类将会变得很简单(一般这样的对象都是实现于某种接口的),只要修改 XML 就可以了。
缺点:
<!-- [if !supportLists]-->l <!-- [endif]-->生成一个对象的步骤变的复杂了,对于不习惯这种方式的人,会觉得有些别扭和不直观。不过这种复杂都已经被容器实现了,对于使用现有的 IOC 容器进行应用开发的人员来说,使用确实相当简单。
<!-- [if !supportLists]-->l <!-- [endif]-->对象生成因为是使用反射编程,在效率上有些损耗。但相对于 ioc 提高的维护性和灵活性来说,这点损耗是微不足道的。
Spring 的 IOC 容器配置详解
依赖注入 DI(dependency injection) 模式
类型名称 | 类型名称 | 描述 | 项目 |
Type1 | 接口注入 | 服务需要实现专门的接口,通过接口,有对象提供这些服务。 | J2EE, |
Type2 | 构造注入 | 使依赖性以构造函数的形式提供,不以 javabean 属性的形式公开 | Spring |
Type3 | 设置注入 | 通过 javabean 的属性(例如 setter 方法)分配依赖性 | Spring |
1. <!-- [endif]-->type1 接口注入
我们开发一个 InjectUserDao 接口,它的用途是将一个 UserDao 实例注入到实现该接口的类中。
InjectUserDao 接口 代码如下:
public interface InjectUserDao {
public void setUserDao(UserDao userDao);
}
UserRegister需要容器为它注入一个UserDao的实例,则它必须实现InjectUserDao接口。UserRegister部分代码如下:
public class UserRegister implements InjectUserDao{
private UserDao userDao = null;//该对象实例由容器注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
// UserRegister的其它业务方法
}
2. type2 构造注入
public class SetStudent {
private Problem problem;
public Student(Problem problem) {
this.problem = problem;
}
public void resolveProblem() {
System.out.print(problem.displayMessage()+"\r");
}
}
对应的配置文件:
<bean id="Problem" class="com.example1.Problem"> <property name="title" > <value>problem title</value> </property> </bean> <bean id="Student" class="com.example1.Student"> <constructor-arg ref="problem"></constructor-arg> </bean>
3. type3 设值注入
3. type3 设值注入
public class SetStudent {
private Problem problem;
public Problem getProblem() {
return problem;
}
public void setProblem(Problem problem) {
this.problem = problem;
}
public void resolveProblem() {
System.out.print(problem.displayMessage()+"\r");
}
}
对应的配置文件:
<bean id="ProblemA" class="com.example1.ProblemA"> <property name="title" > <value>problem title</value> </property> </bean> <bean id="ProblemB" class="com.example1.ProblemB"> <property name="title" > <value>problem title</value> </property> </bean> <bean id="Student" class="com.example1.Student"> <property name="problem" ref="ProblemA" /> </bean> <bean id="StudentA" class="com.example1.StudentA"> <property name="problem" ref="ProblemA" /> </bean> <bean id="StudentB" class="com.example1.StudentB"> <property name="problem" ref="ProblemC" /> </bean>
3 种类型的对比
接口注入模式具有侵入性,一般情况不使用,这里不加说明
2. <!-- [endif]-->type2 构造注入的优势
在构造期即创建一个完整、合法的对象 ” 。对于这条 java 设计原则, type2 无疑是最好的响应者
避免了烦琐的 setter 方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,更加易读。
由于没有 setter 方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后对组件“不变”的稳定状态,无须担心上层代码在调用过程中执行 setter 方法对组件依赖关系产生破坏,特别是对于 singleton 模式的组件而言。这可能对整个系统产生重大的影响。
由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。对于调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的层次清晰性提供了保证。
通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要。
设置注入的优势
对于习惯了传统的 javabean 开发的程序员来说,通过 setter 方法设定依赖关系显得更加直观。更加自然
如果依赖关系较为复杂, type2 模式的构造函数也会相当的庞大,这样 type3 模式往往更加简洁
对于某些第三方类库而言,可能要求我们的组件必须提供一个默认的构造函数。此时 type2 类型的依赖注入机制就体现出其局限性。