`
javafenger
  • 浏览: 246856 次
  • 来自: ...
文章分类
社区版块
存档分类
最新评论

AOP应用实例--Spring事务处理及其AOP框架的内幕

阅读更多
        Spring框架中成功吸引人的一点就是容器事务的管理,提供了一个轻量级的容器事务处理,针对的对象是普通的java类,使用Spring事务管理的话,你可以按照自己的业务把一些相关的方法纳入其事务管理里面,这就避免了程序员在处理事务的过程中繁琐的工作.同时这些也是ejb2.X规范里面吸引人的一点,这在spring里面都很好的提供.虽然在跨容器的事务管理,spring里面并没有提供,但是对于一般的web程序来说,也不需要仅仅为了那些功能而不得不使用ejb.不过,最近jboss的嵌入式的ejb容器也可以做的更小了,也是开源中的选择之一.无论技术是怎样发展的,当前,我们先来研究其中AOP实现的方法.

       事实上,Spring中的事务处理是通过AOP思想来实现的,Spring AOP与Aspect J和JBoss具有很大的不同,首先,使用Spring AOP框架的用户要记住的一点是,Spring AOP针对的是方法层次上的实现,而其他两者对字段也提供了支持.说到Spring AOP的内幕,其实也不难,对于有接口的类,使用的是Java内部类提供的Proxy;而对于那些不实现接口的类,使用的是cglib库,动态创建一个子类来实现.

      在Spring AOP中提供了4种处理切入类型:around,before,after,introduction.顾名思义,

     1)around是针对具体的某个切入点的方法(比如,现在有个OrderBook方法,around的切入类型是就这个方法的内部调用,是通过java的元数据,在运行时通过Method.invoke来调用,具有返回值,当发生意外的时候会终止.记住的一点是,返回值.);

    2)before是在方法调用前调用(在OrderBook方法前调用,但是没有返回值,同时在通常意外情况下,会继续运行下一步方法.记住的一点是没有返回值);

    3)after和before刚好相反,没有什么特别的地方.

    4)introduction是一个更加特殊的,但功能更加强大的切入类型.比如(你现在有Book对象,Computer对象,还有几十个这种业务对象,现在你希望在每个这样的对象中都加入一个记录最后修改的时间.但是你又不希望对每个类都进行修改,因为太麻烦了,同时更重要的一点,破坏了对象的完整性,说不定你以后又不需要这个时间数据了呢...这时怎么办呢?Spring AOP就为你专门实现这种思想提供了一个切入处理,那就是introduction.introduction可以为你动态加入某些方法,这样可以在运行时,强制转换这些对象,进行插入时间数据的动作,更深的内幕就是C++虚函数中的vtable思想).不过这种动态是以性能作为代价的,使用之前要慎重考虑,这里我们谈的是技术,所以就认为他是必需的.

     好,现在我们就拿第四种来进行举例说明Spring AOP的强大之处:

1)假设创建了一个BookService接口及其实现方法(你自己的业务对象):

//$ID:BookService.java Created:2005-11-6 by Kerluse Benn
package com.osiris.springaop;

public interface BookService {
 public String OrderComputerMagazine(String userName,String bookName);
 public String OrderBook(String userName,String bookName);
}

//$ID:BookServiceImpl.java Created:2005-11-6 by Kerluse Benn
package com.osiris.springaop;

public class BookServiceImpl implements BookService{
 public String OrderBook(String name,String bookName) {
  // TODO Add your codes here
  String result=null;
  result="订购"+bookName+"成功";
  return result;
 }

 public String OrderComputerMagazine(String userName, String bookName) {
  // TODO Add your codes here
  String result=null;
  result="订购"+bookName+"成功";
  return result;
 }
}

2)事实上你还有很多这样的对象,现在我们希望在每个对象中添加我们的功能最后修改的时间,功能如下:

//$ID:IAuditable.java Created:2005-11-7 by Kerluse Benn
package com.osiris.springaop.advices.intruduction;

import java.util.Date;

public interface IAuditable {
 void setLastModifiedDate(Date date);
 Date getLastModifiedDate();
}

3)因为我们使用的切入类型是introduction,Spring AOP为我们提供了一个描述这种类型的接口IntroductionInterceptor,所以我们的切入实现处理,也需要实现这个接口:

//$ID:AuditableMixin.java Created:2005-11-7 by Kerluse Benn
package com.osiris.springaop.advices.intruduction;

import java.util.Date;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.IntroductionInterceptor;

public class AuditableMixin implements IAuditable,IntroductionInterceptor{
 private Date lastModifiedDate;
 
 public Object invoke(MethodInvocation m) throws Throwable {
  // TODO Add your codes here
  if(implementsInterface(m.getMethod().getDeclaringClass())){
   return m.getMethod().invoke(this,m.getArguments());
   //invoke introduced mthod,here is IAuditable
  }else{
   return m.proceed(); //delegate other method
  }
 }

 public Date getLastModifiedDate() {
  // TODO Add your codes here
  return lastModifiedDate;
 }

 public void setLastModifiedDate(Date date) {
  // TODO Add your codes here
  lastModifiedDate=date;
 }

 public boolean implementsInterface(Class cls) {
  // TODO Add your codes here
  return cls.isAssignableFrom(IAuditable.class);
 }
 
}
4)ok,现在业务对象BookService类有了,自己希望添加的处理也有了IAuditable,那就剩下使用Spring AOP框架的问题了,配置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>
 <!-- Beans -->
 <bean id="BookServiceTarget" class="com.osiris.springaop.BookServiceImpl" singleton="false"/>

 <!-- introduction advice -->
 <bean id="AuditableMixin" class="com.osiris.springaop.advices.intruduction.AuditableMixin" singleton="false"/>

 <!-- Introduction advisor -->
 <bean id="AuditableAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor"
  singleton="false">
  <constructor-arg>
   <ref bean="AuditableMixin"/>
  </constructor-arg>
 </bean>
 
 <bean id="BookService" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="target">
   <ref bean="BookServiceTarget"/>
  </property>
  
  <property name="singleton">
   <value>false</value>
  </property>
  
  <!-- force to use cglib -->
  <property name="proxyTargetClass">
   <value>true</value>
  </property>
  
  <!-- introduction methods -->
  <property name="proxyInterfaces">
   <value>com.osiris.springaop.advices.intruduction.IAuditable</value>
  </property>
  
  <property name="interceptorNames">
   <list>
    <value>AuditableAdvisor</value>
   </list>
  </property>
 </bean>
 
</beans>

以上就是配置文件,现在我们假设使用业务对象如下,这里是一个简单测试类:

//$ID:MainApp.java Created:2005-11-6 by Kerluse Benn
package com.osiris.springaop;

import java.util.Date;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

import com.osiris.springaop.advices.intruduction.IAuditable;

public class MainApp {
 /**
  * @param args
  * @author Kerluse Benn
  */
 public static void main(String[] args) throws Exception{
  // TODO Add your codes here
  BeanFactory factory=new XmlBeanFactory(new FileSystemResource("bean.xml"));
  BookService bookService=(BookService)factory.getBean("BookService");
  IAuditable auditable=(IAuditable)bookService;
  System.out.print(bookService.OrderBook("Kerluse Benn","Professional C#"));
  auditable.setLastModifiedDate(new Date());
  System.out.println(" 订购时间为"+auditable.getLastModifiedDate());
  Thread.sleep(10000);
  System.out.print(bookService.OrderBook("Kerluse Benn","Expert j2ee one-on-one"));
  auditable.setLastModifiedDate(new Date());
  System.out.println(" 订购时间为"+auditable.getLastModifiedDate());
 }
}

输出结果:
订购Professional C#成功 订购时间为Mon Nov 07 11:35:20 CST 2005
订购Expert j2ee one-on-one成功 订购时间为Mon Nov 07 11:35:30 CST 2005

看见上面黑体字:

IAuditable auditable=(IAuditable)bookService;

由于bookService对象事实上已经实现了IAuditable接口,通过Spring AOP的introduction切入实现,所以在运行时(熟悉C++的vtable模型的可以在大脑里想一下)可以转换,我们就可以随意添加自己的接口方法了.

好了,关于Spring AOP就介绍到这了,其他相关的内容可以参考相应的书籍,这篇文章的目的主要是为了介绍一下AOP思想应用的强大之处.具体的相关应用还包括用户操作验证等等.



分享到:
评论

相关推荐

    Spring Aop使用实例

    **Spring AOP 使用实例** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的一个重要组成部分,它提供了一种在不修改原有代码的情况下,通过代理方式添加额外功能的技术。这种技术使得我们...

    spring-aop-3.0.xsd spring-beans-3.0 spring-context-3.0.xsd spring-mvc-3.1.xsd

    Spring AOP(面向切面编程)是 Spring 框架的一个重要部分,它允许开发者在不修改源代码的情况下,实现跨切面的关注点,如日志、事务管理等。`spring-aop-3.0.xsd` 是 Spring AOP 的 XML 配置文件,定义了与 AOP ...

    spring aop xml 实例

    在Java开发领域,Spring框架以其强大的功能和灵活性深受开发者喜爱,而Spring AOP(面向切面编程)则是Spring框架中的一个重要组成部分。AOP允许开发者定义“切面”,它是一种将关注点分离的方式,使得我们可以把...

    spring 应用aop 实例

    在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从核心业务逻辑中分离出来,比如日志记录、事务管理、权限控制等。本实例将深入探讨如何在Spring 4.0版本中实现AOP。 首先,AOP的...

    AOP入门------------------实例

    以上实例展示了如何使用AOP进行日志记录和事务管理,实际上,AOP在J2EE应用中有着广泛的应用。通过理解并熟练掌握AOP,我们可以编写更简洁、更易于维护的代码,提高软件质量。在实际开发中,根据业务需求灵活运用AOP...

    spring-aop实例

    Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种强大的方式来实现横切关注点,如日志、事务管理、安全性等,从而解耦应用程序的核心业务逻辑。在Spring AOP中,关注点被模块化为独立的“切面”...

    spring2-aop入门实例教程

    ### Spring2-AOP入门实例教程知识点详解 #### 一、Spring框架概述 - **轻量级J2EE开发框架**:Spring是一个轻量级的Java应用框架,它为开发复杂的企业级应用提供了一种简化的方法。 - **发展历程**:自2002年发布...

    小马哥讲 Spring AOP 编程思想 - API 线索图.pdf

    Spring AOP 是Spring框架提供的一个功能模块,它允许开发者将横切关注点(cross-cutting concerns)从业务逻辑中解耦出来,通过在方法调用前后进行拦截来实现。这些横切关注点通常是一些与业务逻辑不直接相关的服务...

    spring-aop实例demo

    在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员定义“切面”,这些切面封装了应用程序中的交叉关注点,如日志、事务管理、权限检查等。Spring AOP是基于代理的,它可以为普通Java对象(POJOs)...

    spring aop实例

    另一个文件"testaop"是一个MyEclipse项目,包含了实际的Spring AOP应用实例。这个项目可以帮助你更好地理解如何在实际项目中集成和使用Spring AOP。你可以直接导入此项目到MyEclipse中,运行并观察AOP如何工作,例如...

    tuling-vip-spring-master.zip

    Spring是一个分层的Java/Java EE应用框架,主要包括IoC(Inversion of Control,控制反转)、AOP(Aspect-Oriented Programming,面向切面编程)两大核心特性,以及MVC(Model-View-Controller,模型-视图-控制器)...

    Spring框架(spring-framework-5.2.6.RELEASE)的jar包

    Spring框架是中国最流行的Java应用开发框架之一,以其模块化、松耦合的特性深受开发者喜爱。5.2.6.RELEASE是Spring框架的一个稳定版本,它包含了一系列的jar包,这些jar包是构建和运行基于Spring的应用程序所必需的...

    Spring AOP配置实例

    通过以上步骤,你就成功地配置了一个基本的Spring AOP实例,实现了对特定方法的日志记录。当然,实际的项目中可能会有更复杂的切面逻辑和通知类型,但这个实例提供了一个很好的起点。你可以根据需要扩展和调整切点...

    Spring-AOP实例

    Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的重要组成部分,它为Java应用程序提供了声明式的企业级服务,如事务管理、性能监控等。本实例将深入探讨Spring AOP的核心概念、配置与...

    SSM框架-----------SpringMVC+Spring+Mybatis框架整合详细教程

    例如,使用Spring的@Transactional注解进行声明式事务管理,通过AOP实现全局异常处理,利用缓存提升查询效率,以及使用Mybatis的动态SQL功能编写灵活的查询语句。 通过本教程的学习,开发者将掌握SSM框架的集成与...

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

    Spring AOP 和 Spring IOC 是 Spring 框架的两个核心组件,它们对于任何基于 Java 的企业级应用开发都至关重要。Spring AOP(面向切面编程)允许开发者在不修改源代码的情况下,通过“切面”来插入新的行为或增强已...

    spring AOP入门实例

    Spring AOP,全称Aspect-Oriented Programming(面向切面编程),是Spring框架的重要组成部分,它为应用程序提供了声明式的企业级服务,如日志、事务管理、安全控制等。在这个入门实例中,我们将深入理解Spring AOP...

    Spring AOP入门及其实例讲解、下载

    **Spring AOP 入门及其实例讲解** 在软件开发中,面向切面编程(Aspect Oriented Programming,简称AOP)是一种编程范式,它旨在提高代码的可重用性,减少冗余,并将关注点分离。Spring框架是Java开发中的一个流行...

    spring1.x使用AOP实例

    Spring 1.x版本虽然已经较为古老,但理解其AOP(面向切面编程)的使用对于学习Spring框架的整体架构和设计理念至关重要。AOP是Spring解决横切关注点问题的重要手段,如日志记录、事务管理等。 首先,让我们来了解...

    spring_aop_拦截实例

    在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员定义横切关注点,如日志、事务管理、性能监控等,并将它们模块化为可重用的组件,称为切面。本实例主要探讨如何在Spring AOP中实现拦截器。 ...

Global site tag (gtag.js) - Google Analytics