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

Spring学习(七)深入理解Spring IoC容器

2016-05-26 23:35 666 查看
IoC:他是Spring容器的内核,AOP、声明式事务等功能都依赖于此功能,它涉及代码解耦,设计模式、代码优化等问题的考量。

接下来使用电影与演员的关系来详细解释一下IoC:
我们来使用电影《无间道》中刘德华所饰演的角色刘建明在天台对白来作为我们学习IoC的示例场景。
那么我们现在便有:
接口类:ActorArrangable、LiuJianming
Java Bean:WuJianDao
接口实现类:LiuDeHua实现LiuJianming接口
执行类:Director
在传统的表演模式中,是剧本与演员直接耦合。即剧本直接指定LiuDeHua来表演



那么在引入角色接口LiuJianming之后,类与类之间的关系变为:



在这种情况下,WuJianDao还是和角色LiuJianming、演员LiuDeHua之间存在耦合关系。

那么我们该如何实现让演员与剧本无关,即剧本只与角色有关,但却必须使LiuDeHua来完成角色的表演。
那么,我们便引入导演类Director
这时,由导演选择剧本,并为剧本定义一个角色LiuJianming,让LiuJianming这个角色插入到剧本当中去。
最后让LiuDeHua来饰演LiuJianming这个角色。



对应到软件当中,导演就像是一个装配器。他来安排演员表演具体的角色。
那么我们现在便可以来谈谈IoC的概念,
IoC从字面意思上可以理解为:

其一 控制
其二 反转

那到底是什么东西的控制被反转了呢?
对应到前面的例子
控制指的是选择LiuJianming角色扮演着的控制权
反转是指这种控制权从WuJianDao剧本中移除,转交到了导演的手中。
那么对于软件来说:就是对应某个接口的控制权从调用类当中来移除,转交到了第三方来决定。
由此也引出了DI的概念:让调用类对某一接口实现类的依赖关系由第三方注入,以移除调用类对某一接口实现类的依赖
接下来看一下IoC的注入类型
IoC从注入方法上看,主要划分为三种类型:
1.构造函数注入:通过调用类的构造函数,将接口实现类通过构造函数变量传入
Public class WuJianDao {
private LiuJianming ljm;
//1:注入刘建明的具体扮演者
public WuJianDao(LiuJianming ljm) {
this.ljm = ljm;
}
public void tianTai() {
ljm.declare(“我想做一个好人!”)
}
}

Public class Director {
public void direct() {
//2.指定角色的扮演者
LiuJianming ljm = new LiuDeHua();
//3.注入具体扮演者到剧本中
WuJianDao wjd = new WuJianDao(ljm);
wjd.tianTai();
}
}


2.属性注入:通过Setter方法完成调用类所需依赖的注入,更加灵活方便
Public class WuJianDao {
private LiuJianming ljm;
//1.属性注入方法
public void setLjm(LiuJianmin ljm) {
this.ljm = ljm;
}
public void tianTai() {
ljm.declare(“我想做一个好人!”)
}
}

Public class Director {
public void direct() {
LiuJianming ljm = new LiuDeHua();
WuJianDao wjd = new WuJianDao();
//2.调用属性Setter方法注入
wjd.setLjm(ljm);
wjd.tianTai();
}


3.接口注入:将调用类所有依赖注入的方法抽取到一个接口中,调用类通过实现该接口提供相应的注入方法。
Public interface ActorArrangable {
void injectLjm(LiuJianming ljm);
}

Public class WuJianDao
implements ActorArrangable {
private LiuJianming ljm;
//1.实现接口方法
public void injectLjm(LiuJianming ljm)
{this.ljm = ljm; }
public void tianTai() {
ljm.declare(“我想做一个好人!”)
}
}

Public class Director {
public void direct() {
LiuJianming ljm = new LiuDeHua();
WuJianDao wjd= new WuJianDao();
wjd.injectLjm(ljm);
wjd.tianTai();
}
}


由于采用接口注入需要额外声明一个接口,这无疑就增加了类的数目。
而且他的效果和属性注入并没有本质上的区别。所以,我们在Spring IoC当中并不提倡采用这种方式。
Spring作为一个容器,通过配置文件或者注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入的工作,
下面是对以上实例进行配置的配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="ljm" class="cn.lovepi.chapter02.ioc.LiuDeHua"/>
<bean id="wjd" class="cn.lovepi.chapter02.ioc.WuJianDao"
p:geli-ref="ljm"/>
</beans>


那么,Spring为什么会有这种神奇般的力量呢?
仅凭一个简单的配置文件,就能魔法般的实现实例化并装配好程序所用的Bean呢。这种神奇的力量归功与JAVA语言本身的类反射功能。
下面,我们就来了解下JAVA语言的反射机制。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring IOC DI Java Web bean