android 控制反转,Spring控制反转(IoC)的理解

Spring框架的核心就是控制反转(Inversion of Control)和依赖注入(Dependency Injection),

通过这两方面来实现松耦合。

一、控制反转(Inversion of Control)和依赖注入

使用IoC,对象是被动的接受依赖类,而不是自己主动的去找。

容器在实例化的时候主动将它的依赖类注入给它。

可以这样理解:控制反转将类的主动权转移到接口上,

依赖注入通过xml配置文件在类实例化时将其依赖类注入。

通过下面的实例来逐步的理解:

首先假设有一个需求,类Business需要调用类Dependency的方法f(),

按照日常的做法,得到下面的代码:

//**类Dependency**

public class Dependency {

public void f() {};

}

//**类Business**

public  class Business {

Dependency d;

public Business() {

d = new Dependency();

}

public void doSth() {

d.f();

}

}

对上述实现做出如下修改:

首先,将Business里的Dependency实例的获得该为setter方式,

其次,将Dependency类改为某个接口的实现。

故可以得到下面新的代码:

//**接口IDependency**

public interface IDependency {

void f();

}

//**类Dependency**

public class Dependency {

public void f() {};

}

//**类Business**

public  class Business {

IDependency d;

public Business() {}   // 不生成实例

public void doSth() {

d.f();

}

public void setDependency(IDependency d) {

this.d = d;

}

}

在新的代码中,

首先,Business的变量d可以接收任何IDependency的实例,

另外,Dependency的实例不是通过Business来获得,而是通过setter(也可以用构造器)来由外部传给它。

这似乎跟我们往常的代码没什么不同,但这已经是一个良好的设计。

关键就是Dependency的实例如何从外部注入给Business呢?

这就要通过xml来实现了。

创建一个SpringFirst.xml,进行简单的配置:

这个配置文件里将Dependency类和Business类加入,并将Dependency作为Business的一个参数。

单有了这个xml文件还不够,还需要一个测试类来加载该xml文件,

spring提供了现成的API,在加载上面的xml的时候,

就进行了如下工作:

. 实例化Dependency类,实例化Business类,

. 并将Dependency的实例作为参数赋给了Business实例的setDependency()方法。

下面是该测试程序:

public class StartServer {

public static void main(String [] args) {

ClassPathResource cr = new ClassPathResource("SpringFirst.xml");

BeanFactory factory = new XmlBeanFactory(cr);

Business b = (Business)factory.getBean("business");

b.doSth();

}

}

上面的程序加载了xml以后,获得id为"business"的bean,即Business类的实例,并调用了其doSth()方法。

由此可见,Business的依赖类Dependency是通过xml来注入的,而且Business是通过接口IDependency来接收Dependency实例。

因此,当我们又有新的IDependency的实现时,只需要修改xml文件即可,测试程序只需要根据xml里的id值来获得需要的参数。

总结上面的例子,对控制反转和依赖注入已经能理解了。

. 依赖类(Dependency)是通过外部(xml)来注入的,而不是由使用它的类(Business)来自己制造,这就是依赖的注入。

. 另一方面,Business对类Dependency的依赖转移到对接口IDependency的依赖,控制权由类转移到了接口,

即由"实现"转移到"抽象"中。这就是控制反转。

二、Spring中bean的基本xml配置

在spring容器内拼凑bean叫作装配。

装配bean的时候,你是在告诉容器,需要哪些bean,以及容器如何使用依赖注入将它们配合在一起。

理论上,bean装配可以从任何资源获得,包括属性文件,关系数据库等,

但xml是最常见的spring 应用系统配置源。

Spring中的几种容器都支持使用xml装配bean,包括:

. XmlBeanFactory ,

. ClassPathXmlApplicationContext ,

. FileSystemXmlApplicationContext ,

. XmlWebApplicationContext

基本的xml配置包括如下几个方面:

1.添加一个bean

2.设置bean的属性

2.1 手动设置

2.1.1 通过Setter方法

2.1.2 通过构造器

2.2 自动设置

其中bean的属性即为bean里的成员变量,这些成员变量值的获得可以通过setter方法,

例如某个属性为name,则setter方法为setName(String name);

或者通过构造器在类被实例化时初始化。

Setter方法(例如setName方法)或者构造器的调用都可以通过在xml文件里进行配置,

从而实现让spring容器来自动进行。

1.添加一个bean

以下是一个例子:

id = “mybean”

Class = “blog.spring.MyBean”

Singleton = “false”

init-method = “initMethod”

destroy-method = “destroyMethod”

autowire = “autowire type”

/>

下面是对该标签里各个属性的解释:

. id :      标识该bean的名称,通过factory.getBean(“id”)来获得实例。

. class :   该bean的类路径。

. singleton : 默认为true,即单实例模式,

每次getBean(“id”)时获取的都是同一个实例,

如果设置为false,即原型模式,则每次获取的是新创建的实例。

. init-method : 在bean实例化后要调用的方法(bean里定义好的方法)。

. Destroy-method : bean从容器里删除之前要调用的方法。

. Autowire : 其属性要通过何种方法进行属性的自动装配。

对于上述的各个属性,id和class是必要的,其他的则可以省略。

例如如果设置了autowire的值,则表明需要自动装配,否则是手动装配。

2.通过Setter方法手动设置bean里的属性

Bean里的属性通过标签来标识。有以下几种情况:

. 简单类型属性

springTest

. 引用其他bean

也可以将改为

这样叫做内部bean,缺点是无法在其他地方重用这个bean的实例。

. 装配集合

共有以下几种集合的装配:

****装配List和数组****

something

otherThing

****装配Set****

something

otherThing

****装配Map****

value1

****装配Properties****

value1

value2

. 设置null

要将一个属性null,需要通过标签,如果不设置,则属性为默认值(在实例化时)而不是null。

3.通过构造器手动设置bean里的属性

假设有如下一个bean:

Public class MyBean {

Public MyBean( String arg1, MyBean1 arg2, String arg3 )

}

则可以在xml里这样配置该bean:

springTest

其中的index是用来标识该参数在构造函数里的位置的,并从0开始。

4.让spring完成自动装配

例如:

id = “mybean”

class = “blog.spring.MyBean”

autowire = “autowire type”

/>

下面是几种autowire type的说明:

. byname : 试图在容器中寻找和需要自动装配的属性名相同的bean或id,如果没有找到相应的bean,则这个属性未被装配上。

. byType : 试图在容器中寻找一个与需要自动装配的属性类型相同的bean或id,如果没有找到,则该属性未被装配上。

. constructor : 试图在容器中寻找与需要自动装配的bean的构造函数参数一致的一个或多个bean,如果没找到则抛出异常。

. autodetect : 首先尝试使用constructor来自动装配,然后再使用byType方式。

从上面可以看出,如果某个bean不手动设置autowire属性,则默认为手动装配。

如果需要将所有bean都设置为自动装配时,可以通过在标签中设置default-autowire属性。

标签是整个xml文档的根,在它下面就是一个个的。

其中default-autowire的值也有byName,byType,constructor,autodetect四种。

例如配置如下:

...

自动装配可能带来不确定性问题。

例如使用byType时可能同时发现两个相同的类型,则不知道该采用哪一个。

所以可能混合采用自动和手动装配。

例如,对某个bean设置为自动装配,而对其某个属性则手动明确的设置其值,

例如:

Autowire = “byType”

>

通过这样的配置,对mybean里的name属性进行手动装配,而对除name外的其他属性就进行自动装配。

阅读(978) | 评论(0) | 转发(0) |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值