疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

spring核心:IOC和AOP


 

  IOC容器

  1.控制反转(Inversion of Control)与依赖注入(DependencyInjection)

  控制反转即IoC (Inversion ofControl),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。

  依赖注入DI是对IOC的另一种描述;DI也就是将应用系统中的各个类的依赖关系先剥离出来,然后在系统运行中根据应用程序之间的调用关系再适时的注入到系统中。

  Class MyBusiness{

  //那么MyContent就和MyBusiness互为依赖关系。

  Private MyContent content;

  }

  2.好莱坞原则

  IoC体现了好莱坞原则,即“不要打电话过来,我们会打给你”。第一次遇到好莱坞原则是在了解模板方法(Template Mathod)模式的时候,模板方法模式的核心是,基类(抽象类)定义了算法的骨架,而将一些步骤延迟到子类中。

  现在来考虑IoC的实现机制,组件定义了整个流程框架,而其中的一些业务逻辑的实现要借助于其他业务对象的加入,它们可以通过两种方式参与到业务流程中,一种是依赖查找(Dependency Lookup),类似与JDNI的实现,通过JNDI来找到相应的业务对象(代码1),另一种是依赖注入,通过IoC容器将业务对象注入到组件中。

  3.依赖查找(Dependency Lookup)

  下面代码展示了基于JNDI实现的依赖查找机制。

  public class MyBusniessObject{

  private DataSource ds;

  private MyCollaborator myCollaborator;

  public MyBusnissObject(){

  Context ctx = null;

  try{

  ctx = new InitialContext();

  ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);

  myCollaborator =

  (MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);

  }}

  代码1依赖查找(Dependency Lookup)代码实现

  依赖查找的主要问题是,这段代码必须依赖于JNDI环境,所以它不能在应用服务器之外运行,并且如果要用别的方式取代JNDI来查找资源和协作对象,就必须把JNDI代码抽出来重构到一个策略方法中去。

  4.依赖注入(Dependency Injection)

  依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。

  下面分别演示3中注入机制。

  代码2待注入的业务对象Content.java

  packagecom.zj.ioc.di;

  publicclassContent {

  publicvoidBusniessContent(){

  System.out.println("do business");

  }

  publicvoidAnotherBusniessContent(){

  System.out.println("do another business");

  }

  }

  MyBusniess类展示了一个业务组件,它的实现需要对象Content的注入。代码3,代码4,代码5,6分别演示构造子注入(ConstructorInjection),设值注入(Setter Injection)和接口注入(Interface Injection)三种方式。

  代码3构造子注入(Constructor Injection)MyBusiness.java

  packagecom.zj.ioc.di.ctor;

  importcom.zj.ioc.di.Content;

  publicclassMyBusiness {

  privateContentmyContent;

  publicMyBusiness(Content content) {

  myContent= content;

  }

  publicvoiddoBusiness(){

  myContent.BusniessContent();

  }

  publicvoiddoAnotherBusiness(){

  myContent.AnotherBusniessContent();

  }

  }

  代码4设值注入(Setter Injection)MyBusiness.java

  packagecom.zj.ioc.di.set;

  importcom.zj.ioc.di.Content;

  publicclassMyBusiness {

  privateContentmyContent;

  publicvoidsetContent(Content content) {

  myContent= content;

  }

  publicvoiddoBusiness(){

  myContent.BusniessContent();

  }

  publicvoiddoAnotherBusiness(){

  myContent.AnotherBusniessContent();

  }

  }

  代码5设置注入接口InContent.java

  packagecom.zj.ioc.di.iface;

  importcom.zj.ioc.di.Content;

  publicinterfaceInContent {

  voidcreateContent(Content content);

  }

  代码6接口注入(Interface Injection)MyBusiness.java

  packagecom.zj.ioc.di.iface;

  importcom.zj.ioc.di.Content;

  publicclassMyBusinessimplementsInContent{

  privateContentmyContent;

  publicvoidcreateContent(Content content) {

  myContent= content;

  }

  publicvoiddoBusniess(){

  myContent.BusniessContent();

  }

  publicvoiddoAnotherBusniess(){

  myContent.AnotherBusniessContent();

  }

  }

  5.依赖拖拽(Dependency Pull)

  最后需要介绍的是依赖拖拽,注入的对象如何与组件发生联系,这个过程就是通过依赖拖拽实现。

  代码7依赖拖拽示例

  public static void main(String[] args) throws Exception{

  //get the bean factory

  BeanFactory factory = getBeanFactory();

  MessageRender mr = (MessageRender) factory.getBean(“renderer”);

  mr.render();

  }

  而通常对注入对象的配置可以通过一个xml文件完成。

  使用这种方式对对象进行集中管理,使用依赖拖拽与依赖查找本质的区别是,依赖查找是在业务组件代码中进行的,而不是从一个集中的注册处,特定的地点执行。

  构造注入和设值注入:两种注入方式的对比

  1、相比之下,设值注入具有如下的优点:

  (1)、与传统的 JavaBean 的写法更相似,程序开发人员更容易理解、接受。通过 Setting 方法设定依赖关系显得更加直观、自然。

  (2)、对于复杂的依赖关系,如果采用构造注入,会导致构造过于臃肿,难以阅读。Spring 在创建 Bean 实例时,需要同时实例化其依赖的全部实例,因而导致性能下降。而使用设值注入,则能避免这些问题。

  (3)、尤其是在某些属性可选的情况下,多参数的构造器更加笨重。

  2、构造注入也不是绝对不如设值注入,在某些特定的场景下,构造注入比设值注入更优秀。构造注入也有如下优势:

  (1)、构造注入可以在构造器中决定依赖关系的注入顺序,有限依赖的优先注入。例如,组件中某些其他依赖关系的注入,尝尝需要依赖于 Datasource 的注入。采用构造注入,可以在代码中清晰地决定注入顺序。

  (2)、对于依赖关系无须变化的 Bean ,构造注入更有用处。因为没有 setting 方法,所有的依赖关系全部在构造器内设定。因此,无须担心后续代码对依赖关系产生的破坏。

  (3)、依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完成透明,更符合高内聚的原则。