Spring中Ioc入门实例

来源:互联网 发布:河南数据统计采集门户 编辑:程序博客网 时间:2024/04/30 12:10

原文链接:http://dev.yesky.com/400/2508400.shtml

Spring中Ioc入门实例

        Spring的模块化是很强的,各个功能模块都是独立的,我们可以选择的使用。

        spring框架最强大的地方就是实现了依赖注入(也叫控制反转IoC),所谓IoC就是一个用XML来定义生成对象的模式,是工厂模式的应用结合了MVC的设计思想,spring框架中到处体现工厂模式。

        依赖注入早期叫控制反转,也可以称反射,他们的意义都相同。当某个 Java 实例(调用者)需要另一个Java 实例(被调用者)时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。而在依赖注入的模式下,创建被调用者的工作(也就是实例化一个类)不再由调用者来完成,通常由 Spring 容器来完成,然后注入调用者,因此称为控制反转,也称为依赖注入。

数据模型

1、如下图所示有三个类,Human(人类)是接口,Chinese(中国人)是一个子类,American(美国人)是另外一个子类。


源代码如下:


package cn.com.chengang.spring;public interface Human {void eat();void walk();}package cn.com.chengang.spring;public class Chinese implements Human {/* (非 Javadoc)* @see cn.com.chengang.spring.Human#eat()*/public void eat() {System.out.println("中国人对吃很有一套");}/* (非 Javadoc)* @see cn.com.chengang.spring.Human#walk()*/public void walk() {System.out.println("中国人行如飞");}}package cn.com.chengang.spring;public class American implements Human {/* (非 Javadoc)* @see cn.com.chengang.spring.Human#eat()*/public void eat() {System.out.println("美国人主要以面包为主");}/* (非 Javadoc)* @see cn.com.chengang.spring.Human#walk()*/public void walk() {System.out.println("美国人以车代步,有四肢退化的趋势");}}
2、对以上对象采用工厂模式的用法如下

  创建一个工厂类Factory,如下。这个工厂类里定义了两个字符串常量,所标识不同的人种。getHuman方法根据传入参数的字串,来判断要生成什么样的人种。
工厂类: Factory.java

package cn.com.chengang.spring;public class Factory {public final static String CHINESE = "Chinese";public final static String AMERICAN = "American";public Human getHuman(String ethnic) {if (ethnic.equals(CHINESE))return new Chinese();else if (ethnic.equals(AMERICAN))return new American();elsethrow new IllegalArgumentException("参数(人种)错误");}}
下面是一个测试的程序,使用工厂方法来得到了不同的“人种对象”,并执行相应的方法。
工厂测试类:Test.java

package cn.com.chengang.spring;public class Test {public static void main(String[] args) {Human human = null;human = new Factory().getHuman(Factory.CHINESE);human.eat();human.walk();human = new Factory().getHuman(Factory.AMERICAN);human.eat();human.walk();}}
控制台的打印结果如下:

3、把上面第2点工厂类模型进行变更成采用Spring的IoC的用法如下:

在项目根目录下创建一个bean.xml文件

bean.xml

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans><bean id="Chinese" class="cn.com.chengang.spring.Chinese"/><bean id="American" class="cn.com.chengang.spring.American"/></beans>
bean.xml的位置如下图,注意不要看花眼把它看成是lib目录下的了,它是在myspring目录下的。


修改Test.java程序如下:
package cn.com.chengang.spring;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class Test {public final static String CHINESE = "Chinese";public final static String AMERICAN = "American";public static void main(String[] args) {// Human human = null;// human = new Factory().getHuman(Factory.CHINESE);// human.eat();// human.walk();// human = new Factory().getHuman(Factory.AMERICAN);// human.eat();// human.walk();ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");Human human = null;human = (Human) ctx.getBean(CHINESE);human.eat();human.walk();human = (Human) ctx.getBean(AMERICAN);human.eat();human.walk();}}

从这个程序可以看到,ctx就相当于原来的Factory工厂,原来的Factory就可以删除掉了。然后又把Factory里的两个常量移到了Test类里,整个程序结构基本一样。

再回头看原来的bean.xml文件的这一句:

<bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>
id就是ctx.getBean的参数值,一个字符串。class就是一个类(包名+类名)。然后在ClientTest类里获得Chinese对象就是这么一句

human = (Human) ctx.getBean(CHINESE);
因为getBean方法返回的是Object类型,所以前面要加一个类型转换。
总结

  (1)也许有人说,IoC和工厂模式不是一样的作用吗,用IoC好象还麻烦一点。

  举个例子,如果用户需求发生变化,要把Chinese类修改一下。那么前一种工厂模式,就要更改Factory类的方法,并且重新编译布署。而IoC只需要将class属性改变一下,并且由于IoC利用了Java反射机制,这些对象是动态生成的,这时我们就可以热插拨Chinese对象(不必把原程序停止下来重新编译布署)

  (2)也许有人说,即然IoC这么好,那么我把系统所有对象都用IoC方式来生成。

  注意,IoC的灵活性是有代价的:设置步骤麻烦、生成对象的方式不直观、反射比正常生成对象在效率上慢一点。因此使用IoC要看有没有必要,我认为比较通用的判断方式是:用到工厂模式的地方都可以考虑用IoC模式。

  (3)在上面的IoC的方式里,还有一些可以变化的地方。比如,bean.xml不一定要放在项目录下,也可以放在其他地方,比如cn.com.chengang.spring包里。不过在使用时也要变化一下,如下所示:

new FileSystemXmlApplicationContext("src/cn/com/chengang/spring/bean.xml");
另外,bean.xml也可以改成其他名字。这样我们在系统中就可以分门别类的设置不同的bean.xml。

  (4)关于IoC的低侵入性。

  什么是低侵入性?如果你用过Struts或EJB就会发现,要继承一些接口或类,才能利用它们的框架开发。这样,系统就被绑定在Struts、EJB上了,对系统的可移植性产生不利的影响。如果代码中很少涉及某一个框架的代码,那么这个框架就可以称做是一个低侵入性的框架。

  Spring的侵入性很低,Humen.java、Chinese.java等几个类都不必继承什么接口或类。但在ClientTest里还是有一些Spring的影子:FileSystemXmlApplicationContext类和ctx.getBean方式等。
现在,低侵入性似乎也成了判定一个框架的实现技术好坏的标准之一。

  (5)关于bean.xml的用法

  bean.xml的用法还有很多,其中内容是相当丰富的。假设Chinese类里有一个humenName属性(姓名),那么原的bean.xml修改如下。此后生成Chinese对象时,“陈刚”这个值将自动设置到Chinese类的humenName属性中。而且由于singleton为true这时生成Chinese对象将采用单例模式,系统仅存在一个Chinese对象实例。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans><bean id="Chinese" class="cn.com.chengang.spring.Chinese" singleton="true"><property name="humenName"><value>陈刚</value></property></bean><bean id="American" class="cn.com.chengang.spring.American"/></beans>







0 0
原创粉丝点击