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

Spring(四):IOC,DI

2014-10-22 15:39 204 查看
包括:

一. IOC概念

二. IOC原理
三. 具体应用

一. IOC概念
        IOC,即 Inversion Of Control 称为控制反转, 是作为 Spring 的 核心功能之一。简单来说,当一个Java实例 A 需要另一个 Java 实例 B 的时候,系统自动提供 实例 B,无须我们手动来创建,这种自动提供的方式,我们就称为控制反转,也可以称为依赖注入(Dependency
Injection)。

二. IOC原理
2.1 创建实体
1. 通过一定的技术读取spring.xml文件(比如通过dom4j技术),然后就可以把读取到的bean元素读取出来存放。比如,先创建一个BeanDefinition类,把spring的xml文件定义的bean的一些信息放在该类中,比如id和name,这样就可以在主方法中定义List<BeanDefinition>beanDefineList;
用来保存xml文件中的多个bean元素。如下:

public class BeanDefinition {
private String id;
private String className;
public BeanDefinition(String id,String className){
this.id = id;
this.className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}


2. 第一步读取到了BeanDefinition,那么第二步就要进行创建,主要使用了反射技术。
    2.1 由于有beanDefineList这个多个bean需要创建,所以先用一个for循环。例如:

for(BeanDefinition beanDefinition: beanDefineList){
//... ...
}

    2.2 创建一个Map<String,Object> singletons 集合,key 为这个 BeanDefinition的 id 属性,value 为 实际的bean 对象。这样我们就可以根据 id 取得bean 实例了。例如:

singletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance());

    当然,需要做一些判断,比如是否为空,是否重复等等。这样就完成了bean的实例化。这里就是反射技术一个很好的应用。

总结:

通过一定的技术读取xml文件。得到bean元素的id和class。
创建Map集合,key为bean元素的id,value为bean元素的class属性对应的实体类。此时要注意,bean元素的class属性只是一个字符串,比如”XX.XX.XX.Student”,而Map集合的value不再是这个字符串,而是这个字符串对应的实体。
怎么创建这个实体,是根据class属性的字符串采用反射技术得到的。

2.2 依赖注入

        例如我们要把一个DAO对象注入到Service对象中,是如何做到的。例如在xml文件中有如下代码:

<bean id = "StudentDAO" class = "XX.XX.XX.StudentDAOImpl" />
<bean id = "StudentService" class = "XX.XX.XX.StudentServiceImpl">
<property name="studentDao" ref = "StudentDAO"></property>
</bean>


1. 我们分析,每个bean元素里面可能有多个<property>元素,那么我们可以先创建一个PropertyDefinition类,专门记录这个<property>元素的信息,如下:
public class PropertyDefinition {
private String name;
private String ref;
public PropertyDefinition(String name,String ref) {
this.name = name;
this.ref = ref;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
}


2. 每个bean元素都有这个<property>元素,而且可能不只一个,所以可以在BeanDefinition中加入一个private
List<PropertyDefinition> propertys属性来代表。如下:
public class BeanDefinition {
private String id;
private String className;
private List<PropertyDefinition> propertys;
public BeanDefinition(String id,String className){
this.id = id;
this.className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<PropertyDefinition> getPropertys() {
return propertys;
}
public void setPropertys(List<PropertyDefinition> propertys) {
this.propertys = propertys;
}
}


3. 之前说过,可以通过一定的技术读取xml文件的bean元素(dom4j技术),同样的,也可以通过这个技术读取到<property>元素。至于怎么读取,就不介绍了。
4. 到目前为止,我们已经得到了几个东西。List<BeanDefinition> beanDefineList;以及Map<String,Object> singletons;以及beanDefineList的属性privateList<PropertyDefinition>
propertys;
5. 这样就可以通过反射技术来进行注入,比如使用 set 方法。

用代码来表示注入过程如下:
1. 首先循环所有的bean,因为每一个bean都可能有注入,代码如下:

for(BeanDefinition beanDefinition: beanDefineList){
//... ...
}

2. 然后我们再来一个循环,循环一个BeanDefinition中的propertys;因为每一个bean都可以有多个注入:

for(PropertyDefinition propertyDefinition:beanDefineList.getPropertys())
//...
}


    每一个propertyDefinition都有一个name和ref。name就是指该一个类中的属性成员,ref就是指之前的bean元素。而之前的bean元素,我们又已经全部创建了,放在了singletons;集合中。

3. 那么怎么把ref所指的bean元素放到一个类的成员属性中。首先我们可以通过反射的技术得到该成员属性的set方法。然后我们再把ref所指的bean元素,也就是singletons;中对应的实例赋给set方法。这样就完成了注入。

Spring注入总结
取得一切必要的信息,比如bean元素(代码中所对应的BeanDefinition),比如property元素(代码中所指PropertyDefinition),还有bean元素对象的实体类(代码中所指singletons)。
利用反射的技术得到一个类中的成员属性的set方法。
利用一定的算法,匹配property元素的ref和成员属性的对应关系。对应了,就用singletons中对应的实例赋给set方法,完成注入。

三. 具体应用

目前的应用主要使用注解的方法来配置,而不再是在Spring的xml文件中配置。如下:
1. 在xml文件中配置对注解的支持,和创建的支持等。如下代码:

<!-- 扫描DAO层和服务层的包 -->
<context:component-scan base-package="com.whc.demo.dao"/>
<context:component-scan base-package="com.whc.demo.serviceImpl"/>
<context:component-scan base-package="com.whc.common.*" />


2. 在Java类中加入注解:常用注解有 @Controller;@Service;@Repository;@Component;在Spring4的新特性中,还有@RestController注解,主要是对@Controller和@ResponseBody注解的合并。代码如下:
@Controller
public class GetUserController {
......
}

3. 依赖注入,即在属性前或者 set 方法 加入@Resource(name = "xx")或者 @Autowired 注解即可完成注入,如下代码:

@Service(value = "getUserServiceImpl")
public class GetUserServiceImpl implements GetUserService{

@Autowired
private GetUserDao getUserDao;
......
}


Ps:
1. 注入又分为设值注入和构造器注入,构造器注入也就是在xml配置文件中使用一个 constructor-arg 标签 。一般使用设值注入比较多,那么使用设值注入的时候,记得需要为属性添加
set 方法,因为 依赖注入依靠反射,需要到 set 方法 注入。

另一篇写得不错的文章:Spring读书笔记-Spring核心机制:依赖注入
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息