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

Spring之IOC控制反转的理解

2018-01-12 16:46 218 查看
Spring IOC简介
beans和context包是IOC容器的基础,BeanFactory 提供的高级配置机制,使得管理各种对象成为可能。 ApplicationContext 是BeanFactory的扩展,功能得到了进一步增强,比如更易 与Spring AOP集成、资源处理(国际化处理)、事件传递及各种不同应用层的context实现 (如针对web应用的WebApplicationContext)。总之,在实际应用更多会选择ApplicationContext,原因是ApplicationContext即继承了BeanFactory的功能,同时又增加的更多支持企业核心内容的支持。

Spring IOC关键概念理解
IOC(Inversion of Control):控制反转,即指获取对象的方式被反转了,我们只需要在applicationContext.xml(Spring的配置文件)文件配置元数据(即指xml)中的bean指定相应class(类)的全路径,Spring中的容器(BeanFactory)会负责类对象的创建、配置和管理这些对象及它们之间的依赖关系,而且这些对象和我们通过new Object()的对象没有区别,这样最终会达到解耦的目的(即减少代码之间的依赖);

Bean:在Spring中,那些组成你应用程序的主体(backbone)及由Spring IoC容器所管理的对象,被称之为bean。 简单地讲,bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。 而bean定义以及bean相互间的依赖关系将通过配置元数据来描述。

容器:即指Spring IOC容器,BeanFactory是容器的实际代表者,他负责bean对象的创建,配置和容纳创建的bean描述并且管理bean;Spring为我们提供了许多易用的BeanFactory实现,
XmlBeanFactory就是最常用的一个。该实现将以XML方式描述组成应用的对象以及对象间的依赖关系。XmlBeanFactory类将获取此XML配置元数据,并用它来构建一个完全可配置的系统或应用
4000




Spring IOC 容器

元数据:我们通常配置的Spring配置xml文件内容,就是元数据;

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> 
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>

<!-- more bean definitions go here -->

</beans>

注入依赖:
依赖注入(DI)背后的基本原理是对象之间的依赖关系(即一起工作的其它对象)只会通过以下几种方式来实现:构造器的参数、工厂方法的参数,或给由构造函数或者工厂方法创建的对象设置属性。因此,容器的工作就是创建bean时注入那些依赖关系。相对于由bean自己来控制其实例化、直接在构造器中指定依赖关系或者类似服务定位器(Service
Locator)模式这3种自主控制依赖关系注入的方法来说,控制从根本上发生了倒转,这也正是控制反转(Inversion of Control, IoC) 名字的由来。 

Spring的IOC关键配置
1.如何定义(创建)一个bean

Spring IoC容器将管理一个或多个bean,这些bean 将通过配置文件中的bean定义被创建(在XML格式中为<bean/>
元素)。

在容器内部,这些bean定义由BeanDefinition 对象来表示,该定义将包含以下信息:

全限定类名:这通常就是已定义bean的实际实现类。

bean行为的定义,这些定义将决定bean在容器中的行为(作用域、生命周期回调等等)

对其他bean的引用,这些引用bean也可以称之为协作bean(collaborators)
或依赖bean(dependencies).

创建bean实例时的其他配置设置。比如使用bean来定义连接池,可以通过属性或者构 造参数指定连接数,以及连接池大小限制等。

上述内容直接被翻译为每个bean定义包含的一组properties。具体的properties属性参考下面的:Spring官方的翻译文档;

2.bean如何实例化

从本质上来说,bean定义描述了如何创建一个或多个对象实例。当需要的时候, 容器会从bean定义列表中取得一个指定的bean定义,并根据bean定义里面的配置元数据 使用反射机制来创建(或取得)一个实际的对象。

当采用XML描述配置元数据时,将通过<bean/>元素的 class属性来指定实例化对象的类型。class 属性 (对应BeanDefinition实例的 Class属性)通常是必须的(不过也有两种例外的情形,见

Section 3.2.3.2.3, “使用实例工厂方法实例化”和
Section 3.6, “bean定义的继承”)。class属性主要有两种用途 :在大多数情况下,容器将直接通过反射调用指定类的构造器来创建bean(这有点类似于 在Java代码中使用new操作符);在极少数情况下,容器将调用 类的静态工厂方法来创建bean实例,class 属性将用来指定实际具有静态工厂方法的类(至于调用静态工厂
方法创建的对象类型是当前class还是其他的class则无关紧要)。

实例化主要有三种方式:用构造器来实例化,使用静态方法实例化,使用实例工厂来实例化;

3.DI-注入依赖(指的就是对象与对象之间的依赖关系通过配置的方式建立)
通过以下几种方式来实现:构造器的参数、工厂方法的参数,或给由构造函数或者工厂方法创建的对象设置属性。DI主要有两种注入方式,即Setter注入构造器注入

3.1(Setter)首先是一个用XML格式定义的Setter DI例子。相关的XML配置如下:

<bean id="exampleBean" class="examples.ExampleBean">

<!-- setter injection using the nested <ref/> element -->
<property name="beanOne"><ref bean="anotherExampleBean"/></property>

<!-- setter injection using the neater 'ref' attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

public class ExampleBean {

private AnotherBean beanOne;
private YetAnotherBean beanTwo;
private int i;

public void setBeanOne(AnotherBean beanOne) {
this.beanOne = beanOne;
}

public void setBeanTwo(YetAnotherBean beanTwo) {
this.beanTwo = beanTwo;
}

public void setIntegerProperty(int i) {
this.i = i;
}
}

3.2(构造器参数的方式)正如你所看到的,bean类中的setter方法与xml文件中配置的属性是一一对应的。接着是构造器注入的例子:
<bean id="exampleBean" class="examples.ExampleBean">

<!-- constructor injection using the nested <ref/> element -->
<constructor-arg>
<ref bean="anotherExampleBean"/>
</constructor-arg>

<!-- constructor injection using the neater 'ref' attribute -->
<constructor-arg ref="yetAnotherBean"/>

<constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

public class ExampleBean {

private AnotherBean beanOne;
private YetAnotherBean beanTwo;
private int i;

public ExampleBean(
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
this.beanOne = anotherBean;
this.beanTwo = yetAnotherBean;
this.i = i;
}
}


4.Bean的生命周期回调
在Bean的创建之前或销毁的时候,我们可能做一些初始化处理或者释放资源的操作;

Spring提供了几个标志接口(marker interface),这些接口用来改变容器中bean的行为;它们包括InitializingBean和DisposableBean。实现这两个接口的bean在初始化和析构时容器会调用前者的afterPropertiesSet()方法,以及后者的destroy()方法。 

Spring在内部使用BeanPostProcessor实现来处理它能找到的任何标志接口并调用相应的方法。如果你需要自定义特性或者生命周期行为,你可以实现自己的
BeanPostProcessor。关于这方面更多的内容可以看Section 3.7, “容器扩展点”

以上仅仅是我基于学习Spring官方翻译文档的一些关键内容记录,具体的学习请参考官方翻译文档

参考:

Spring官方翻译文档:http://shouce.jb51.net/spring/beans.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring 控制反转 IOC