spring学习3-Ioc和DI的简单介绍

原创
2014/03/16 15:52
阅读数 230

控制反转(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类,结果如下

image

当然,我们注入的不知是常量,也可以注入其他的类。

比如现在我们有一个类叫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 + " ] " ; } }

运行结果:

image

 

在bean标签里其实还有个属性scope,这个属性可以说是标识这个通过spring ioc获取的类的生命周期,其默认值是单例(Singleton),不过我们执行多少次context.getBean(“engine”),获得的都是同一个对象,这个属性一共有四个值

  • singleton:单例(默认)
  • prototype:每次调用一次getBean方法,就new一个对象出来
  • request:用于web开发将bean放入request中,在同一个request中获取的是同一个bean
  • session:用于web开发将bean放入session中。

有关ioc和DI跟深入的使用,待我学习完再和大家分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部