Spring【2】

来源:互联网 发布:陈思 网络 编辑:程序博客网 时间:2024/05/17 21:07

[所有关于Spring的文章均是来自Spring入门书籍.pdf,但是本人记忆不好,所以坚持每天敲打两节吧,但是本书确实比较难懂,可能是TaiWan版本,所以如有人知晓原版或E版请告知,感谢]

入门03-依赖注入DI

   IoC模式基本上是一个更高层的概念,在Martin FlowerInversion of Control Containers and the Dependency Injection pattern中谈到,实现IoC有两种方式:Dependency InjectionService Locator

Spring所采用的是Dependency Injection来实现IoC,中文翻译为依赖注入,依赖注入的意思是:保留抽象介面,让组建依赖于抽象介面,当组建要与其他实际的物件发生关系依赖时,藉过抽象介面来注入依赖的实际物件。看看下面的程序:

Public class BusinessObject{

  Private FloppyWriter writer = new FloppyWriter();

  .. .. ..

  public void save(){

  .. .. ..

  writer.saveToFloppy();

}

}

BusinessObject依赖于实际的FloppyWriter,为了让BusinessObject获得重用性,我们不让BusinessObject依赖于实际的FloppyWriter,而是依赖于抽象的介面:

public interface IdeviceWriter{

  public void saveToDevice();

}

 

public class BusinessObject{

  private IdeviceWriter writer;

  public void setDeviceWriter(IdevicWriter writer){

    this.writer = writer;

  }

 

  public void save(){

  .. ..

  writer.saveToDevice();

  }

}

 

public class FloppyWriter implement IdeviceWriter{

  public void saveToDevice(){

.. ..

//实际存储至Floppy的程序代码

}

}

 

public class UsbDiskWriter implement IdeviceWriter{

  public saveToDevice(){

.. ..

//实际存储至UsbDisk的程序代码

}

}

如果今天BusinessObject想要与UsbDiskWriter物件发生依赖关系,可以这么建立:

BusinessObject.setDeviceWriter(new UsbDiskWriter);

由于BusinessObject依赖于抽象介面,在需要建立依赖关系时,我们可以透过抽象介面注入依赖的实际物件。

依赖注入在Martin Fowler的文章谈到三种实现方式:interface injectionsetter injectionconstructor injection。并分别称为type1 IoCtype2 IoCtype3 IoC

上面的Business Object所显示的是type2 injection,透过setter注入依赖关系,而type3 IoC,则是建立在方法上的注入依赖关系,例如:

Public class BusinessObject{

  Private IdeviceWriter writer;

  Public BusinessObjec(IdeviceWriter writer){

  This.writer = writer;

}

public void save(){

.. ..

writer.saveToDevice();

}

}

Spring鼓励的是setter injection,但是也允许您使用constructor injection,使用setterconstructor的注入依赖关系视您的需求而定,使用constructor的好处之一视,您可以在建构物件的同时一并完成依赖关系的建立,然而腰间里的物件关系很多,则会在建构函数上留下一长串的参数,这是使用setter会是个不错的选择,另一方面,setter可以有明确的名称可以了解注入的物件会是什么,像是setXXX()这样的名称回避记忆constructor上某参数位置代表物件来的好。

Type1 IoCinterface injection,使用会要求实际介面,这个机面视容器所用的,容器知道街面上所规定的方法,它可以呼叫实际介面的物件来完成依赖关系的注入,例如:

Public interface IdependencyInjection{

  Public void createDependency(Map dependObjects)

}

public class BusinessObject implement IdependencyInjection{

  private Map dependObjects;

  public void createDependency(Map dependObjects){

  this.dependObjects = dependObjects;

  //在这里实现与BusinessObject的依赖关系

  .. .. ..

}

  public void save(){

.. ..

writer.saveToDevice();

}

}

如果要完成依赖关系注入的物件,必须实现IdependencyInjection介面,并交由容器管理,容器会呼叫被管理物件的createDependency()方法来完成依赖关系的建立。

在上面的例子中,type1 IoC要求BusinessObject实现特定的介面,这就使得BusinessObject依赖于容器,如果日后BusinessObject要脱离目前这个容器,就必须修改程序,想想在更复杂的依赖关系中产生了更多复杂的介面,组建与容器的依赖会更加复杂,最终使得组建无法从容器中脱离。

所以type1 IoC具有很强的侵入性,使用它来实现依赖注入使得组建组建依赖于容器,降低组建的重用性。

Spring的核心是个IoC容器,您可以用setterconstuctor的方式来实现您的业务组建,至于物件与物件之间的关系建立,则透过状态设定,让Spring在执行期间根据状态的设定来为您建立物件之间的依赖关系,您不必特地撰写一些Helper来自行建立这些物件之间的依赖关系,这不仅减少了大量的程序书写,也降低了物件之间的耦合度。

入门04-第一个Spring程序

    来撰写我们的第一个组建(component),它只是一个简单的JavaBean,用来向新的使用者打招呼:

Package onlyfun.caterpillar;

public class HelloBean{

 

private String helloWord = “Hello World”;

 

public void setHelloWord(String helloWord){

  this.helloWord = helloword;

}

 

public String getHelloWord(){

  return helloword;

}

}

HelloBean有预设的“HelloWorld”字符串,我们也可以透过setter来设定新的招呼,不过我们不亲自撰写程序来作这些事,而是在组态档案定义,由Spring来为我们作设定的动作,我们撰写bean.xml:

<?xml version = “1.0” encoding = “UFT-8”?>

<!DOCTYPE      beans           PUBLIC          “-//SPRING/DTD            BEAN/EN”

http://www.springframwork.org/dtd/spring-beans.dtd”>

<beans>

<bean id = “helloBean” class = “onlyfun.caterpillar.HelloBean>

<property name = “helloWord”><value>Hello!Justin!</value></property>

  </bean>

</beans>

Bean.xml中定义了JavaBean的别名与来源类别,<property>标签设定了我们希望注入至JavaBean的字符串值,bean.xml必须在您的classpath可以存取到的目录中,也许是现行的工作的目录,在Web程序中可以是在classes目录下,我们这边使用的是单机编程的方式,将使用FileInputStream读取bean.xml,所以将之置于现行的工作目录中,接着我们撰写第一个简单的测试程序:

Pakcage onlyFun caterpillar;

 

Import java.io.*;

Import org.springframework.beans.factory.Beans.BeanFactory;

Import org.springframework.beans.factory.Beans.xml.XMLBeanFactory;

 

Public class SpringTest{

  Public static void main(String[] args) throws IOExcetption{

  InputStream is = new FileInputStream(“bean.xml”);

  BeanFactory factory = new XMLBeanFactory(is);

 

  HelloBean hello = (HelloWord) factory.getBean(“helloBean”);

  System.out.printlb(helli.getHelloWord());

}

}

这是个从比较低层次的角度来使用SpringIoC容器功能,藉由BeanFactory来读取状态档案并完成依赖关系注入,这边的依赖是什么呢?只得是HelloBean相依于String物件,透过setter所保留的介面,我们使用setter injection来完成这个依赖注入,而不是将招呼语句写死为HelloBeanBeanFactory是整个Spring的重点所在,整个Spring的核心都围绕这它,在这里使用的是XMLBeanFactory,负责读取XML状态档案,当然我们也可以使用propertis档案,这之后再介绍。

BeanFactory读取Bean的状态设定并完成关系维护之后,我们藉由getBean()方法并指定Bean的别名来取得实例,来侃侃实际运行之后的效果:

如果今天您想要改变招呼语,则只要更改bean.xml就可以了,不用修改主要的程序,从比较一般的角度来看,就意味着如果您想要改变一些物件之间的依赖关系,则主要修改组状态档即可,而不用修改一行程序。