`
lzth
  • 浏览: 142289 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring中的AOP与IOC

阅读更多


在 J2EE的整个发展历程中,现在正是一个非常时刻。从很多方面来说,J2EE都是一个伟大的成功:它成功地在从前没有标准的地方建立了标准;大大提升了企业级软件的开放程度,并且得到了整个行业和开发者的广泛认可。然而,J2EE在一些方面已经开始捉襟见肘。J2EE应用开发的成本通常很高。J2EE应用项目至少和从前的非J2EE项目一样容易失败——如果不是更容易失败的话。这样的失败率高得让人难以接受。在这样的失败率之下,软件开发几乎变成了碰运气。而在J2EE遭遇失败的场景中,EJB通常都扮演着重要的角色。因此,J2EE社群不断地向着更简单的解决方案、更少使用EJB的方向发展[1]。然而,每个应用程序都需要一些基础设施,拒绝使用EJB并不意味着拒绝EJB所采用的基础设施解决方案。那么,如何利用现有的框架来提供这些基础设施服务呢,伴随着这个问题的提出,一个轻量级的J2EE解决方案出现了,这就是Spring Framework。

  Spring是为简化企业级系统开发而诞生的,Spring框架为J2EE应用常见的问题提供了简单、有效的解决方案,使用Spring,你可以用简单的POJO(Plain Old Java Object)来实现那些以前只有EJB才能实现的功能。这样不只是能简化服务器端开发,任何Java系统开发都能从Spring的简单、可测试和松耦合特征中受益。可以简单的说,Spring是一个轻量级的反向控制(IoC)和面向切面编程(AOP)容器框架[3]。Spring IoC,借助于依赖注入设计模式,使得开发者不用理会对象自身的生命周期及其关系,而且能够改善开发者对J2EE模式的使用;Spring AOP,借助于Spring实现的拦截器,开发者能够实现以声明的方式使用企业级服务,比如安全性服务、事务服务等。Spring IoC和 Spring ; AOP组合,一起形成了Spring,这样一个有机整体,使得构建轻量级的J2EE架构成为可能,而且事实证明,非常有效。没有Spring IoC的Spring AOP是不完善的,没有Spring AOP的Spring IoC是不健壮的。本文是以Spring架构的成功的实际商务系统项目为背景,阐述了反向控制原理和面向切面的编程技术在Spring框架中的应用,同时抽取适量代码示意具体应用,并和传统开发模式进行对比,展示了Spring framework的简单,高效,可维护等优点。

  1、Spring IoC 1.1 反向控制原理

  反向控制是Spring框架的核心。但是,反向控制是什么意思?到底控制的什么方面被反向了呢?2004年美国专家Martin Fowler发表了一篇论文《Inversion of Control Containers and the Dependency Injection pattern》阐述了这个问题,他总结说是获得依赖对象的方式反向了,根据这个启示,他还为反向控制提出了一个更贴切的名字:Dependency Injection(DI 依赖注入)。

  通常,应用代码需要告知容器或框架,让它们找到自身所需要的类,然后再由应用代码创建待使用的对象实例。因此,应用代码在使用实例之前,需要创建对象实例。然而,IoC模式中,创建对象实例的任务交给IoC容器或框架(实现了IoC设计模式的框架也被称为IoC容器),使得应用代码只需要直接使用实例,这就是IoC。相对IoC 而言,“依赖注入”的确更加准确的描述了这种设计理念。所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。

  1.2 IoC在Spring中的实现

  任何重要的系统都需要至少两个相互合作的类来完成业务逻辑。通常,每个对象都要自己负责得到它的合作(依赖)对象。你会发现,这样会导致代码耦合度高而且难于测试。使用IoC,对象的依赖都是在对象创建时由负责协调系统中各个对象的外部实体提供的,这样使软件组件松散连接成为可能。下面示意了 Spring IoC 应用,步骤如下:

  (1)定义Action接口,并为其定义一个execute方法,以完成目标逻辑。多年前,GoF在《Design Pattern:Elements of Reusable Object-Oriented Software》一书中提出“Programming to an Interface,not an implementation”的原则,这里首先将业务对象抽象成接口,正是为了实施这个原则。

  (2)类UpperAction实现Action接口,在此类中,定义一个String型的域message,并提供相应的setter和getter方法,实现的execute方法如下:

public String execute (String str) {



 return (getMessage () + str).toUpperCase () ;

}

  (3)编写Spring配置文件(bean.XML)

<beans>



<bean id="TheAction" class="net.chen.spring.qs.UpperAction">

<property name="message">

<value>HeLLo</value>

</property>

</bean>

</beans>

  (4)测试代码

public void testQuickStart () {



 ApplicationContext ctx=new

 FileSystemXmlApplicationContext ("bean.xml");

 Action a= (Action) ctx.getBean ("TheAction");

 System.out.println (a. execute ("Rod Johnson"));

}

  上面的测试代码中,我们根据"bean.xml"创建了一个ApplicationContext实例,并从此实例中获取我们所需的Action实现,运行测试代码,我们看到控制台输出:

……



HELLO ROD JOHNSON

  仔细观察一下上面的代码,可以看到:

  (1)我们的组件并不需要实现框架指定的接口,因此可以轻松的将组件从Spring中脱离,甚至不需要任何修改,这在基于EJB框架实现的应用中是难以想象的。

  (2)组件间的依赖关系减少,极大改善了代码的可重用性。Spring的依赖注入机制,可以在运行期为组件配置所需资源,而无需在编写组件代码时就加以指定,从而在相当程度上降低了组件之间的耦合。

  Spring给我们带来了如此这般的好处,那么,反过来,让我们试想一下,如果不使用Spring框架,回到我们传统的编码模式,情况会是怎样呢?

  首先,我们必须编写一个配置文件读取类,以实现Message属性的可配置化。

  其次,得有一个Factory模式的实现,并结合配置文件的读写完成Action的动态加载。于是,我们实现了一个ActionFactory来实现这个功能:

public class ActionFactory {



 public static Action getAction (String actionName) {Properties pro = new Properties ();

 try {

  pro.load (new FileInputStream ("config.properties"));

  String actionImplName =(String)pro.get(actionName);

  String actionMessage =(String) pro.get (actionName+"_msg");

  Object obj =Class.forName (actionImplName).newInstance ();

  BeanUtils.setProperty(obj,"message",actionMessage);

  return (Action) obj;

 } catch (FileNotFoundException e) {

  ……

 }

}

  配置文件则采用properties文件形式如下所示:

TheAction=net.chen.spring.qs.UpperAction



TheAction_msg=HeLLo

  测试代码也作相应修改。现在不论实现的好坏,总之通过上面新增的多行代码,终于实现了类似的功能。如果现在有了一个新的需求,这样这个ActionFactory每次都新建一个类的实例,显然这对系统性能不利,考虑到我们的两个Action都是线程安全的,修改一下ActionFactory,保持系统中只有一个Action实例供其它线程调用。另外Action对象创建后,需要做一些初始化工作。修改一下ActionFactory,使其在创建Action实例之后,随即就调用Action.init方法执行初始化。Action的处理这样就差不多了。下面我们来看看另外一个Factory

  ……

  往往这些系统开发中最常见的需求,会导致我们的代码迅速膨胀,而Spring IoC的出现,则大大缓解了这样的窘境。通过以上实例,可以看出,Spring IoC为我们提供了如下几方面的优势:

  (1)应用组件不需要在运行时寻找其协作者,因此更易于开发和编写应用;

  (2)由于借助于IoC容器管理组件的依赖关系,使得应用的单元测试和集成测试更利于展开;

  (3)通常,在借助于IoC容器关系业务对象的前提下,很少需要使用具体IoC容器提供的API,这使得集成现有的遗留应用成为可能。

  因此,通过使用IoC能够降低组件之间的耦合度,最终,能够提高类的重用性,利于测试,而且更利于整个产品或系统集成和配置。

2、Spring AOP

  2.1 面向切面编程基础

  通常,系统由很多组件组成,每个组件负责一部分功能,然而,这些组件也经常带有一些除了核心功能之外的附带功能 。系统服务如日志、事务管理和安全经常融入到一些其他功能模块中。这些系统服务通常叫做交叉业务,这是因为它们总是分布在系统的很多组件中。通过将这些业务分布在多个组件中,给我们的代码引入了双重复杂性。

  (1) 实现系统级业务的代码在多个组件中复制。这意味着如果你要改变这些业务逻辑,你就必须到各个模块去修改。就算把这些业务抽象成一个独立模块,其它模块只是调用它的一个方法,但是这个方法调用也还是分布在很多地方。

  (2) 组件会因为那些与自己核心业务无关的代码变得杂乱。一个向地址录中添加条目的方法应该只关心如何添加地址,而不是关心它是不是安全或支持事务的。

  此时,我们该怎么办呢?这正是AOP用得着的地方。AOP帮助我们将这些服务模块化,并把它们声明式地应用在需要它们的地方,使得这些组件更加专注于自身业务,完全不知道其它涉及到的系统服务。

  这里的概念切面,就是我们要实现的交叉功能,是应用系统模块化的一个方面或领域。切面的最常见例子就是日志记录。日志记录在系统中到处需要用到,利用继承来重用日志模块是不合适的,这样,就可以创建一个日志记录切面,并且使用AOP在系统中应用。下图展示了切面应用方式

图表 1 应用切面

  其中,通知Advice是切面的实际实现。连接点Joinpoint是应用程序执行过程中插入切面的地点,这个地点可以是方法调用,异常抛出,甚至可以是要修改的字段,切面代码在这些地方插入到你的应用流程中,添加新的行为。切入点Pointcut定义了Advice应该应用在那些连接点,通常通过指定类名和方法名,或者匹配类名和方法名式样的正则表达式来指定切入点。

  2.2 AOP在Spring中的实现

  基于AOP,业界存在各种各样的AOP实现,比如,JBoss AOP、Spring AOP、ASPectJ、 Aspect Werkz等。各自实现的功能也不一样。AOP实现的强弱在很大程度上取决于连接点模型。目前,Spring只支持方法级的连接点。这和一些其他AOP框架不一样,如AspectJ和JBoss,它们还提供了属性接入点,这样可以防止你创建特别细致的通知,如对更新对象属性值进行拦截。然而,由于 Spring关注于提供一个实现J2EE服务的框架,所以方法拦截可以满足大部分要求,而且Spring的观点是属性拦截破坏了封装,让Advice触发在属性值改变而不是方法调用上无疑是破坏了这个概念。

  Spring的AOP框架的关键点如下:

  (1)Spring实现了AOP联盟接口。在Spring AOP中,存在如下几种通知(Advice)类型

  Before通知:在目标方法被调用前调用,涉及接口org.springFramework.aop.MethodBeforeAdvice;

  After通知:在目标方法被调用后调用,涉及接口为org.springframework.aop.AfterReturningAdvice;

  Throws通知:目标方法抛出异常时调用,涉及接口org.springframework.aop.MethodBeforeAdvice;

  Around通知:拦截对目标对象方法调用,涉及接口为org.aopalliance.intercept.MethodInterceptor。

  (2)用Java编写Spring通知,并在Spring的配置文件中,定义在什么地方应用通知的切入点。

  (3)Spring的运行时通知对象。代理Bean只有在第一次被应用系统需要的时候才被创建。如果你使用的是ApplicationContext,代理对象在BeanFactory载入所有Bean的时候被创建。Spring有两种代理创建方式。如果目标对象实现了一个或多个接口暴露的方法,Spring将使用JDK的 java.lang.reflect.Proxy类创建代理。这个类让Spring动态产生一个新的类,它实现所需的接口,织入了通知,并且代理对目标对象的所有请求。如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的子类。在创建这个子类的时候,Spring将通知织入,并且将对目标对象的调用委托给这个子类。此时,需要将Spring发行包lib/cglib目录下的JAR文件发布到应用系统中。

  2.3 Spring AOP的优势

  借助于Spring AOP,Spring IoC能够很方便的使用到非常健壮、灵活的企业级服务,是因为Spring AOP能够提供如下几方面的优势:

  (1)允许开发者使用声明式企业服务,比如事务服务、安全性服务;EJB开发者都知道,EJB组件能够使用J2EE容器提供的声明式服务,但是这些服务要借助于EJB容器,而Spring AOP却不需要EJB容器,借助于Spring的事务抽象框架就可以这些服务。

  (2)开发者可以开发满足业务需求的自定义切面;

  (3)开发Spring AOP Advice很方便。因为这些AOP Advice仅是POJO类,借助于Spring提供的ProxyFactoryBean,能够快速的搭建Spring AOP Advice。

  3、结语

  本文详细阐述了Spring背后的IoC原理和AOP技术,以实际成功项目为背景,抽取简短片断,展示了Spring架构J2EE应用系统的原理。Spring IoC借助于依赖注入机制,减轻了组件之间的依赖关系,同时也大大提高了组件的可移植性,组件得到了更多的重用机会。借助于Spring AOP,使得开发者能声明式、基于元数据访问企业级服务,AOP合理补充了OOP技术,Spring AOP合理地补充了Spring IoC容器。Spring IoC与Spring AOP组合,使得Spring成为成功的J2EE架构框架,并能与标准的EJB等标准对抗,EJB不再是必需品。Spring已经冲入了J2EE的核心,将引领整个J2EE开发、架构的方向。
分享到:
评论

相关推荐

    spring练习AOP与IOC

    在这个“spring练习AOP与IOC”的主题中,我们将深入探讨这两个关键概念。 **依赖注入(IOC)** 依赖注入是Spring框架的基础,它是一种设计模式,允许对象在运行时通过外部源获取其依赖,而不是自行创建或查找。...

    Spring的Aop和Ioc示例

    **Spring AOP与IOC的结合** Spring的AOP和IOC可以协同工作,为应用程序提供更高级别的抽象。例如,你可以定义一个事务管理的切面,当被标记的业务方法执行时,这个切面会自动管理事务的开始、提交或回滚。这可以...

    关于spring的AOP ,IOC,DI的理解

    Spring的核心特性包括AOP(面向切面编程)和IOC(控制反转),以及依赖注入(DI)。以下是对这些概念的详细解释: **面向切面编程(AOP)** AOP是一种编程范式,它允许开发者将关注点从主业务逻辑中分离出来,例如...

    springioc和spring aop

    Spring框架是Java开发中不可或缺的一部分,它通过提供两种核心特性——控制反转(IoC)和面向切面编程(AOP)来简化应用的构建。理解并掌握这两种技术对于任何Java开发者来说都至关重要。 **控制反转(IoC)**,也...

    spring的aop_ioc

    【Spring的AOP和IOC详解】 Spring框架是Java开发中不可或缺的一部分,它的核心特性包括依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)。这两个特性都极大地提升了代码的...

    Java Spring代理模式AOP-IOC分析

    在本文中,我们提供了一个示例项目,演示了如何使用Spring实现AOP和IOC。该项目中,我们定义了一个Math类,并使用静态代理和动态代理来扩展Math类的行为。同时,我们还使用Spring的IOC容器来管理Math类和代理对象,...

    Spring中IOC/AOP的说明和例子

    在Spring框架中,IOC(Inversion of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程)是两个核心的概念,它们极大地提高了软件开发的灵活性和可维护性。 **IOC(控制反转)**是Spring的核心...

    以注解方式模拟Spring IoC AOP

    在Spring框架中,依赖注入(Inversion of Control, IoC)和面向切面编程(Aspect Oriented Programming, AOP)是两大核心特性。本篇将深入探讨如何通过注解方式来模拟Spring的这两种机制,帮助你理解其底层原理。 #...

    Spring IOC和Spring AOP_spring aop_springIOC

    Spring框架是Java开发中最常用的轻量级框架之一,它的核心特性包括依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,简称AOP)。这两个概念是Spring框架的基石,极大地简化了...

    Spring的AOP IOC

    一个机遇Spring3的入门小案例,里面主要简单演示了Spirng配置文件如何配置自动扫描包,控制类、服务类、Dao类如何加注解,被IOC扫描装入容器中。还有AOP例子的演示,有before after afterreturn afterthrow,还有...

    spring AOP 引入jar包,spring IOC 引入Jar包

    在提供的 `lib` 压缩包中,应包含 Spring AOP 和 Spring IOC 相关的 jar 包,如 `spring-aop-x.x.x.jar` 和 `spring-context-x.x.x.jar` 等,它们是使用这两个功能的基础。请确保引入正确的版本,并正确配置到项目的...

    Spring IOC AOP MVC 简单例子

    在`SpringAOP`目录中,可能包含了定义切面、通知(advice)、切入点(pointcut)等内容。AOP的实现通常通过定义切面类,其中包含通知方法,并通过切入点表达式确定这些通知在何时何地执行。这使得代码更加模块化,...

    Spring AOP、IOC、cxf、任务调度所需jar包以及配置文件

    在IT领域,Spring框架是Java开发中的核心工具,它提供了许多功能来简化应用程序的构建,如依赖注入(IOC)、面向切面编程(AOP)以及服务整合。本资源包聚焦于Spring的这些关键特性,同时也涉及到CXF服务、任务调度...

    spring ioc和aop原理流程图(详细)

    Spring 框架是Java开发中的核心框架,它主要由两个关键部分组成:IOC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。这两个概念是Spring框架的核心特性,极大地简化了企业...

    spring_aop_ioc完全讲解

    在Spring框架中,AOP(面向切面编程)和IOC(控制反转)是两个核心概念,它们极大地简化了Java应用的开发和维护。下面将详细解释这两个概念以及如何在实际应用中使用它们。 **控制反转(Inversion of Control, IOC...

    java Spring代理模式AOP-IOC结合

    Spring 的 IoC 容器可以与 AOP 框架集成,我们可以使用 IoC 配置的方式来实现 AOP。我们可以在配置文件中定义 Aspect 和切面,并在运行时织入目标类中。 七、使用 XML 配置 Spring AOP 切面 Spring 提供了一个 XML...

    Spring中IOC(反转控 制) 和 AOP(面向方面编程)

    **Spring中的IOC与AOP结合** Spring的IOC和AOP可以协同工作,提升系统的可维护性和灵活性。例如,我们可以使用AOP来实现事务管理,定义一个事务切面,然后在需要事务控制的方法上应用这个切面。由于这些事务管理...

    Spring AOP IOC源码笔记.pdf

    Spring框架是Java开发中不可或缺的一部分,它主要由两个核心组件构成:IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。本笔记将深入探讨这两个概念以及它们在Spring中...

    spring Aop/Ioc

    AOP(面向切面编程)和IOC(控制反转)是Spring框架的两个关键特性,它们极大地提高了代码的可维护性和可扩展性。 **面向切面编程(AOP)** 面向切面编程是一种编程范式,它允许程序员将关注点分离到不同的模块,...

    Spring 的IOC和AOP特点

    Spring的核心:IOC与AOP。IOC是控制反转或依赖注入,AOP是面向切面编程。

Global site tag (gtag.js) - Google Analytics