控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转还有一个名字叫做依赖注入(Dependency Injection)。简称DI。
以上是来自于百度百科中关于IOC和DI的简单介绍,从中我们可以看到ioc的主要作用是减少类与类之间的耦合程度,在spring中,ioc的表现为类的实例化由原本程序员自己创建对象的动作转为由spring容器创建对象。
在不使用IOC的情况下,我们实例化一个类
IEngine engine
=
new
QiyouEngine();
在这个语句中我们用到了IEngine接口和其实现类QiyouEngine,这样这个类就需要引用这两个类,如果需要改动实现类,则需要修改代码,这就违反了面向对象设计中的”开闭原则“。想要解耦这段代码,一般的解决可以使用工厂模式对其解耦
1
public
class
Main{
2
public
static
void
main(String args[]){
3
IEngine engine
=
EngineFactory.getEngine();
4
engine.doSomething();
5
}
6
}
7
8
9
public
class
EngineFactory{
10
public
static
getEngine(){
11
return
new
QiyouEngine();
12
}
13
}
如果再进一步,可以使用工厂模式+配置文件+反射来实现
比如我们的配置文件叫config.property,里面配置
engine=com.example.QiyouEngine;
在工厂中我们就可以修改成
1
public
class
EngineFactory {
2
3
public
static
IEngine getEngine()
throws
Exception{
4
//
读取配置文件
5
Properties prop
=
new
Properties();
6
String rootPath
=
System.getProperty(
"
user.dir
"
);
7
File f
=
new
File(rootPath
+
File.separator
+
"
config
"
+
File.separator
+
"
config.property
"
);
8
InputStream in
=
new
BufferedInputStream(
new
FileInputStream(f));
9
prop.load(in);
10
String className
=
prop.getProperty(
"
engine
"
);
11
12
//
根据反射获得类
13
IEngine engine
=
(IEngine) Class.forName(className).newInstance();
14
return
engine;
15
}
16
}
这样只要修改配置文件中的实现类名就可以修改程序中的实现类,从而达到不用修改代码的目的。
和上面的例子相似,spring也有着自己的配置文件。
这里我在src目录下创建了一个applicationContext.xml配置文件,其内容是
1
<?
xml version="1.0" encoding="UTF-8"
?>
2
<
beans
xmlns
="http://www.springframework.org/schema/beans"
3
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
4
xsi:schemaLocation
="http://www.springframework.org/schema/beans
5
http://www.springframework.org/schema/beans/spring-beans.xsd"
>
6
7
<
bean
id
="engine"
class
="com.demo.spring.car.QiyouEngine"
>
8
</
bean
>
9
</
beans
>
在代码中我们可以这么写:
1
public
static
void
main( String[] args )
2
{
3
ApplicationContext context
=
new
ClassPathXmlApplicationContext(
"
applicationContext.xml
"
);
4
IEngine engine
=
(IEngine) context.getBean(
"
engine
"
);
5
engine.doSomething();
6
}
这和刚刚的效果是一样的。
如果大家在找IOC的时候一般都会伴随着DI这个词,在spring中,ioc和di是紧密联系的,下面我们演示一下DI是什么样子的。
现在有一个类叫QiyouEngine,其中有个属性是发动机的排量cc,如果一般的写法,我们会在对象创建后通过调用set方法,把值塞到对象中,在spring中可以在配置文件中实现。我们修改一下刚刚xml文件在engine bean中添加属性:
<
bean
id
="engine"
class
="com.demo.spring.car.QiyouEngine"
>
<
property
name
="cc"
value
="2.0"
></
property
>
</
bean
>
在代码中我们加入cc成员变量,并为其添加set的方法
1
public
class
QiyouEngine
implements
IEngine {
2
3
private
String cc;
//
排量
4
5
public
String getCc() {
6
return
cc;
7
}
8
9
public
void
setCc(String cc) {
10
this
.cc
=
cc;
11
}
12
13
public
void
description() {
14
System.out.println(
"
我是汽油发动机\n
"
+
this
.toString());
15
}
16
17
@Override
18
public
String toString() {
19
return
"
QiyouEngine [cc=
"
+
cc
+
"
]
"
;
20
}
21
22
}
在创建完对象后,spring会自动调用set的方法把值塞入对象中。
再运行一边Main类,结果如下
当然,我们注入的不知是常量,也可以注入其他的类。
比如现在我们有一个类叫Car,它有两个属性,一个是name,另一个是engine,我们要做的就是把刚刚的QiyouEngine注入到Car中
<
bean
id
="car"
class
="com.demo.spring.car.Car"
>
<
property
name
="name"
value
="宝马"
></
property
>
<
property
name
="engine"
ref
="engine"
></
property
>
</
bean
>
图片中可以看到engine用的是ref,而不是value,这个就是引用其他类的关键
main类我们修改一下,直接获得car类
public
static
void
main( String[] args )
{
ApplicationContext context
=
new
ClassPathXmlApplicationContext(
"
applicationContext.xml
"
);
Car car
=
(Car) context.getBean(
"
car
"
);
System.out.println(car);
}
Car类的定义
public
class
Car {
private
IEngine engine;
private
String name;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name
=
name;
}
public
IEngine getEngine() {
return
engine;
}
public
void
setEngine(IEngine engine) {
this
.engine
=
engine;
}
@Override
public
String toString() {
return
"
Car [engine=
"
+
engine
+
"
, name=
"
+
name
+
"
]
"
;
}
}
运行结果:
在bean标签里其实还有个属性scope,这个属性可以说是标识这个通过spring ioc获取的类的生命周期,其默认值是单例(Singleton),不过我们执行多少次context.getBean(“engine”),获得的都是同一个对象,这个属性一共有四个值
- singleton:单例(默认)
- prototype:每次调用一次getBean方法,就new一个对象出来
- request:用于web开发将bean放入request中,在同一个request中获取的是同一个bean
- session:用于web开发将bean放入session中。
有关ioc和DI跟深入的使用,待我学习完再和大家分享。
来源:oschina
链接:https://my.oschina.net/u/557735/blog/208669