3.1 依赖和依赖注入
依赖注入带来的好处:
动态替换Bean依赖对象,程序更灵活:替换Bean依赖对象,无需修改源文件:应用依赖注入后,由于可以采用配置文件方式实现,从而能随时动态的替换Bean的依赖对象,无需修改java源文件;
更好实践面向接口编程,代码更清晰:在Bean中只需指定依赖对象的接口,接口定义依赖对象完成的功能,通过容器注入依赖实现;
更好实践优先使用对象组合,而不是类继承:因为IoC容器采用注入依赖,也就是组合对象,从而更好的实践对象组合。
采用对象组合,Bean的功能可能由几个依赖Bean的功能组合而成,其Bean本身可能只提供少许功能或根本无任何功能,全部委托给依赖Bean,对象组合具有动态性,能更方便的替换掉依赖Bean,从而改变Bean功能;
而如果采用类继承,Bean没有依赖Bean,而是采用继承方式添加新功能,,而且功能是在编译时就确定了,不具有动态性,而且采用类继承导致Bean与子Bean之间高度耦合,难以复用。
增加Bean可复用性:依赖于对象组合,Bean更可复用且复用更简单;
降低Bean之间耦合:由于我们完全采用面向接口编程,在代码中没有直接引用Bean依赖实现,全部引用接口,而且不会出现显示的创建依赖对象代码,而且这些依赖是由容器来注入,很容易替换依赖实现类,从而降低Bean与依赖之间耦合;
代码结构更清晰:要应用依赖注入,代码结构要按照规约方式进行书写,从而更好的应用一些最佳实践,因此代码结构更清晰。
从以上我们可以看出,其实依赖注入只是一种装配对象的手段,设计的类结构才是基础,如果设计的类结构不支持依赖注入,Spring IoC容器也注入不了任何东西,从而从根本上说“如何设计好类结构才是关键,依赖注入只是一种装配对象手段”。
前边IoC一章我们已经了解了Bean依赖容器,那容器如何注入Bean的依赖资源,Spring IoC容器注入依赖资源主要有以下两种基本实现方式:
构造器注入:就是容器实例化Bean时注入那些依赖,通过在在Bean定义中指定构造器参数进行注入依赖,包括实例工厂方法参数注入依赖,但静态工厂方法参数不允许注入依赖;
setter注入:通过setter方法进行注入依赖;
方法注入:能通过配置方式替换掉Bean方法,也就是通过配置改变Bean方法 功能。
3.1.2 注入方式
构造器注入:通过配置构造参数实现,构造参数就是依赖。处理构造方式,还可以通静态工厂,实例工厂方法进行构造器注入
一、根据参数索引注入,使用标签“
二、根据参数类型进行注入,使用标签“
三、根据参数名进行注入,使用标签“
以下为测试类:
3.1.3 setter注入:通过构造器,静态工厂和实例工厂实例化bean后,调用bean的setter方法进行注入依赖
属性为private访问级别,不建议public,如private String message;
属性必要时通过一组setter(修改器)和getter(访问器)方法来访问;
配置方式:
准备测试类进行测试
3.1.4常量注入
Spring容器将此字符串转换成属性所需要的类型,如果转换出错,将抛出相应的异常。
Spring容器目前能对各种基本类型把配置的String参数转换为需要的类型。
注:Spring类型转换系统对于boolean类型进行了容错处理,除了可以使用“true/false”标准的Java值进行注入,还能使用“yes/no”、“on/off”、“1/0”来代表“真/假”,所以大家在学习或工作中遇到这种类似问题不要觉得是人家配置错了,而是Spring容错做的非常好。
3.1.5 注入集合 set 数组
注入集合配置
private List
list; 配置文件:
1
2
3
set注入:
Collection类型:因为Collection类型是Set和List类型的基类型,所以使用或标签都可以进行注入,配置方式完全和以上配置方式一样
private Collection col;
4
5
6
数组注入:
private String [] array;
private String [][] array1;
1
2
3
1
2
3
4
5
注入map类型:
private Map
map;
1
2
然后开始编写测试类进行测试:
public class HelloServiceImplimplements HelloApi{
private StringuserName;
private Integerindex;
private Listlist;
private Collectioncol;
private Mapmap;
private Propertiespro;
private String []array;
private String [][]array1;
@Override
public void sayHello() {
System.out.println("index:" +index +", userName:" +userName);
for (String str :list) {
System.out.print("list:" + str);
}
System.out.println("");
for (String c :col) {
System.out.print("set:" + c);
}
System.out.println("");
for (String s :map.keySet()) {
System.out.print("map:" +map.get(s) +",");
}
System.out.println("");
}
......省略setter方法
}
测试类:
@Test
public void test(){
BeanFactory factory =new ClassPathXmlApplicationContext("com/comverse/timesheet/config/dispatcher-servlet.xml");
HelloApi helloApi = factory.getBean("setBean", HelloApi.class);
helloApi.sayHello();
}
总结:
一、构造器注入:
1)常量值
简写:
全写:
2)引用
简写:
二、setter注入:
1)常量值
简写:
全写:
2)引用
简写:
3)数组:
4)列表:没有简写形式
5)集合:
6)字典
简写:
全写:
7)Properties:没有简写形式
使用p命名空间简化setter注入:
xmlns:p="http://www.springframework.org/schema/p" :首先指定p命名空间;