`

Spring2.0 AOP 之Before,After,Thrown,Around Advice

阅读更多

编程式的事务管理---
编程式的事务管理可以清楚地控制事务的边界,也就是让您自行实现事务开始时间、撤消操作的时机、结束时间等,可以实现细粒度的事务控制

声明式的事务管理---
Spring声明式的事务管理依赖它的AOP框架来完成
使用声明事务管理的好处是,事务管理不能侵入您所开发的组件

 

在Spring 2.0里要使用AOP的话,大大的简化了,不管是程序书写还是xml 配置,下面我说一下我的学习和使用过程:

 

我以日志功能为例子,假如我们写了一个method,然后我们想在这个method执行做一件事,执行后做一件事,或是发生异常时怎么样,有的人在想那还不简单,我直接在在这个方法里加上不就行了,但是再想想当一个项目做大后,用这种方法会给以后的维护带来很多麻烦,因为你已经把这些本不属于程序逻辑的事情也耦合到里面了,如果加的地方多的话,以后麻烦可就大了,而利用Spring AOP  想加这个日志功能就简单了,完全与程序逻辑解耦,以后想添改什么的,单独去处理就方便好多了。在Spring 2.0里不再需要去实现好多的接口去做这些事情,配置也很简单了,

 

讲解背景如下:

我有一个接口 IHello

 

public interface IHello {
    public void hello(String name);
}

 

有一个实现类HelloSpeaker

 

public class HelloSpeaker implements IHello {

    public void hello(String name) {
        System.out.println("Hello,"+name);
    }

}

 

 1.Before Advice

  现在我想在hello方法执行前加个log怎么做呢,这里我们要加个class 叫 LogAspect

 

 专门去处理log

 

 public class LogAspect {
   
    private Logger logger=Logger.getLogger(this.getClass().getName());

 

    public void before(JoinPoint jointPoint) {
        logger.log(Level.INFO, "method starts..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
    }

}

 

 然后建个spring基于xml schema的文件

 

 

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans  xmlns ="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation ="http://www.springframework.org/schema/beans    
  6.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd    
  7.     http://www.springframework.org/schema/aop   
  8.     http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9. <bean id="logAspect" class="LogAspect"/>  
  10. <bean id="helloSpeaker" class="HelloSpeaker"/>  
  11. <!-- Based XML Schema -->  
  12. <aop:config>  
  13.     <aop:pointcut id="logHello" expression="execution(* IHello.*(..))"/>  
  14.     <aop:aspect id="logging" ref="logAspect">  
  15.         <aop:before pointcut-ref="logHello" method="before"/>  
  16. </beans>  

 

 

 

再写个TestClass

 

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans-config.xml");
        IHello helloSpeaker=(IHello)context.getBean("helloSpeaker");
        helloSpeaker.hello("Jack");
    }

 

 现在可运行了,但是运行前确保加上asm-*.jar 2.2.1或2.2.2 version ,asm-attrs-2.2.2.jar, asm-commons.jar我的是2.2.的

 

 aspectjweaver-1.5.3.jar     commons-logging-1.0.4.jar

 

spring所需的就不用说了。然后运行结果如下:

 

2009-2-23 15:38:59 LogAspect before
信息: method starts...IHello.hello

Hello,Jack

 

2.After Advice

 

有两种:After和Afterreturning(可以设置目标方法调用的传回值)

 

现在原LogAspec里加个方法:

 

    public void after(JoinPoint jointPoint){
        logger.log(Level.INFO, "method ends..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
    }

beans-config.xml里加上:

 

<aop:after pointcut-ref="logHello" method="after"/>

 

运行后成了:

 

2009-2-23 15:42:27 LogAspect before
信息: method starts...IHello.hello
2009-2-23 15:42:27 LogAspect after
信息: method ends...IHello.hello
Hello,Jack

 

有人说不对啊,这哪里是前和后啊,这里要说明,log是由另一个线程进行操作的,并不影响原有程序的流程。

 

 

3.After Throwing Advice:

 

现在原LogAspec里加个方法:

 

    public void afterThrowing(JoinPoint jointPoint,Throwable throwable){
        logger.log(Level.INFO, "Logging that a " + throwable +
                "\nException was thrown in..."+
                jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
    }

 

配置文件:

 

 <aop:after-throwing pointcut-ref="logHello" throwing="throwable" method="afterThrowing"/>

 

现在故意把hello里修改一下让其引发异常:

 

System.out.println("Hello,"+Integer.parseInt(name));//Testing Exception

 

运行结果如下:

 

2009-2-23 15:46:30 LogAspect before
信息: method starts...IHello.hello
2009-2-23 15:46:30 LogAspect after
信息: method ends...IHello.hello
2009-2-23 15:46:30 LogAspect afterThrowing
信息: Logging that a java.lang.NumberFormatException: For input string: "Jack"
Exception was thrown in...IHello.hello
java.lang.NumberFormatException: For input string: "Jack"

 

 

4. Around Advice :

 

这个可以实现在前和后加上log

 

同样增加一个方法:

 

    public Object invoke(ProceedingJoinPoint jointPoint) throws Throwable{
       
        logger.log(Level.INFO, "method starts..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
       
        Object retVal=jointPoint.proceed();
       
        logger.log(Level.INFO, "method ends..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());

       
        return retVal;
    }

 

 

配置xml文件:

 

<aop:around pointcut-ref="logHello" method="invoke"/>

 

运行结果如下:

 

2009-2-23 15:49:04 LogAspect invoke
信息: method starts...IHello.hello
2009-2-23 15:49:04 LogAspect afterThrowing
信息: Logging that a java.lang.NumberFormatException: For input string: "Jack"
Exception was thrown in...IHello.hello
java.lang.NumberFormatException: For input string: "Jack"

 

大家一看就会发现啊!后面的log没有执行,这里可以告诉我们用Around实现前和后加入log和分别用Before和After的区别之一了。

 

 

前面所说的都是基于XML Schema的,其实还提供了另外的方式

 

基于 Annotation方式

 

我先把最后的样子贴出来吧:

 

 

  1. @Aspect //based Annotation   
  2. public class LogAspect {   
  3.        
  4.     private Logger logger=Logger.getLogger(this.getClass().getName());   
  5.        
  6.     @Pointcut("execution(* IHello.*(..))")   
  7.     private void logging(){}   
  8.        
  9.     @Before("logging()")    //based Annotation   
  10.     public void before(JoinPoint jointPoint) {   
  11.         logger.log(Level.INFO, "method starts..."  
  12.                 + jointPoint.getSignature().getDeclaringTypeName() + "."  
  13.                 + jointPoint.getSignature().getName());   
  14.     }   
  15.        
  16.     @AfterReturning(pointcut="logging()",returning="retVal")   
  17.     public void afterReturning(JoinPoint jointPoint,Object retVal){   
  18.         logger.log(Level.INFO, "method ends..."  
  19.                 + jointPoint.getSignature().getDeclaringTypeName() + "."  
  20.                 + jointPoint.getSignature().getName());   
  21.     }   
  22.     @After(pointcut="logging()")   
  23.     public void after(JoinPoint jointPoint){   
  24.         logger.log(Level.INFO, "method ends..."  
  25.                 + jointPoint.getSignature().getDeclaringTypeName() + "."  
  26.                 + jointPoint.getSignature().getName());   
  27.     }   
  28.        
  29.     @AfterThrowing(pointcut="logging()",throwing="throwable")   
  30.     public void afterThrowing(JoinPoint jointPoint,Throwable throwable){   
  31.         logger.log(Level.INFO, "Logging that a " + throwable +   
  32.                 "\nException was thrown in..."+   
  33.                 jointPoint.getSignature().getDeclaringTypeName() + "."  
  34.                 + jointPoint.getSignature().getName());   
  35.     }   
  36.        
  37.        
  38.     @Around("loggint()")   
  39.     public Object invoke(ProceedingJoinPoint jointPoint) throws Throwable{   
  40.            
  41.         logger.log(Level.INFO, "method starts..."  
  42.                 + jointPoint.getSignature().getDeclaringTypeName() + "."  
  43.                 + jointPoint.getSignature().getName());   
  44.            
  45.         Object retVal=jointPoint.proceed();   
  46.            
  47.         logger.log(Level.INFO, "method ends..."  
  48.                 + jointPoint.getSignature().getDeclaringTypeName() + "."  
  49.                 + jointPoint.getSignature().getName());   
  50.            
  51.         return retVal;   
  52.     }   
  53.        
  54.        
  55.        
  56. }  

 

 

 大家会看到有@Aspect,·@Before这些就是基于Annotation 的方式了,代表什么意义,大家去查询Spring AOP相关资料去了解还有execution(* IHello.*(..))这些也是。

 

这样写配置文件就简单了

 

<!-- <aop:aspectj-autoproxy/> -->

 

就这一句就行了,其它的都不用写了。

 

大家可以去思考两种方式各自的优势。

 

 

 

自己的笔记:

spring中的JDBC的生命式事物管理整个服务层:

//一个普遍性的让整个服务层成为事务性
<bean id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="basicDataSource"/>  //数据源
</bean>
<aop:config>
    //定义了 一个切面,也可以说是一个拦截器
    <aop:pointcut id="jdbcMethod" expression="execution(* test.service.*.*(..))"/>
   //通知器(advisor)把切面与 'txAdvice' 绑定在一起
    <aop:advisor advice-ref="jdbcTransactionAdvice" pointcut-ref="jdbcMethod"/>
</aop:config>
   //事务封装
    <tx:advice id="jdbcTransactionAdvice" transaction-manager="jdbcTransactionManager">
        <tx:attributes>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="remove*" propagation="REQUIRED"/>
           </tx:attributes>
    </tx:advice>

分享到:
评论

相关推荐

    Spring 2.0 AOP 完整例子

    网上找了很多例子多数都不能运行。包括after,before,round,throw切入,可对类直接拦截,不需要定义接口文件,自己研究了2天整理出来的。 Spring AOP 的完整例子,可直接运行。带jar包。

    Spring2.0宝典源代码

    1. **AOP(面向切面编程)增强**:Spring 2.0加强了对AOP的支持,允许开发者定义更复杂的切面,如注解驱动的切面,提供了更多的通知类型,如around、before、after等,使得代码更加模块化和可维护。 2. **注解驱动...

    spring-aop.jar各个版本

    spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-2.5.2.jar spring-aop-2.5.4.jar spring-aop-2.5.5.jar spring-aop-2.5.6.jar spring-aop-3.0.0.RELEASE.jar spring-aop-3.0.2.RELEASE.jar spring-aop-sources...

    SPRING2.0中文文档

    Spring 2.0的AOP增强了切入点表达式,使得定位切点更加灵活,并引入了基于注解的切面定义,让切面编写更加直观。 四、数据访问集成 Spring 2.0在数据访问层提供了对各种持久化技术的集成,包括JDBC、ORM(Hibernate...

    Spring2.0中文教程

    Spring 2.0的主要设计原则之一是依赖注入,它允许组件之间松耦合。DI通过容器管理对象及其依赖关系,而不是由对象自行创建或查找依赖。这提高了代码的可测试性,并简化了系统维护。 2. **AOP(面向切面编程)** ...

    spring2.0 jar包

    @Aspect注解用于定义切面,@Before、@After、@Around等用于指定通知类型。此外,Spring还支持自定义注解作为切入点表达式,提高了代码可读性。 三、数据访问集成 在Spring 2.0中,对数据访问层进行了全面升级,支持...

    spring2.0中文手册及使用指南 chm

    Spring 2.0 是一个非常重要的Java框架,它在企业级应用开发中占据了核心地位,尤其是在基于Java的轻量级应用程序上下文(IoC)和面向切面编程(AOP)方面。本手册和使用指南提供了全面的Spring 2.0相关知识,包括其...

    spring2.0学习源码

    例如,@Before、@After、@Around等注解可以直接应用于方法上,简化了事务管理、日志记录等跨切面的处理。 另一个显著的改进是依赖注入(DI)的增强。Spring 2.0支持了对构造器、setter方法和接口的自动装配,同时...

    spring 2.0使用AOP实例(基于Annotation的配置方式)

    然后,我们使用`@Before`、`@After`、`@AfterReturning`、`@AfterThrowing`和`@Around`这些注解来定义不同类型的的通知。这些注解分别对应于方法调用前、后、成功返回、抛出异常时和包围整个方法调用。 ```java @...

    spring2.0 中文教程

    2. **AOP(面向切面编程)**:Spring 2.0提供了更强大的面向切面编程支持,使得开发者可以将关注点分离,如日志、事务管理等,从而降低代码复杂性。AOP代理包括JDK动态代理和CGLIB代理,允许开发者定义切入点和通知...

    详尽的Spring2.0学习提纲

    Spring 2.0是Java开发中的一个里程碑,它在企业级应用开发中扮演着至关重要的角色,特别是对于依赖注入(IoC)和面向切面编程(AOP)的支持。本学习提纲旨在为初学者提供一份详尽的Spring 2.0学习指南,帮助他们系统...

    spring 2.0使用AOP实例(基于XML的配置方式)

    Spring支持五种不同类型的Advice:前置通知(Before)、后置通知(After)、返回后通知(After Returning)、异常后通知(After Throwing)和环绕通知(Around)。 4. **切点(Pointcut)**:匹配连接点的规则或...

    Spring 2.0 源代码

    2. **AOP(面向切面编程)**:Spring 2.0提供了更强大的面向切面编程支持,允许开发者定义切面、通知(advisors)和切点(pointcuts),并将其应用于业务代码,实现如日志、事务管理等功能。切面可以是接口、类或...

    spring2.0中文参考手册.rar

    1. **AOP(面向切面编程)增强**:Spring 2.0 提供了更强大的面向切面编程支持,允许开发者定义更复杂的切面,包括基于注解的切点表达式和更多的通知类型。这使得代码更加整洁,业务逻辑与系统服务(如事务管理)...

    SPRING2.0开发详解

    Spring 2.0提供了更为强大的AOP支持,能够更方便地将这些关注点与业务逻辑分离。 - **声明式事务管理**:通过配置XML或注解(`@Transactional`)来管理事务边界,简化了复杂的事务代码。 - **自定义切面**:允许...

    精通spring2.0源代码

    《精通Spring 2.0源代码》是一本深入解析Spring框架核心原理的书籍,由罗时飞主编。这本书通过对Spring 2.0版本的源代码进行深入剖析,旨在帮助读者全面理解Spring的工作机制,提升在实际开发中的应用能力。源代码的...

    spring2.0技术手册_源代码(全十章)

    《Spring 2.0 技术手册》是学习和深入理解Spring框架不可或缺的参考资料,而提供的源代码无疑为开发者提供了亲自动手实践的机会。在这个压缩包中,包含了该手册涉及的全部十章节的源码,这为我们深入研究Spring 2.0...

    Spring2.0技术手册

    本书介绍了Spring 2.0的新特性,诸如Spring 2.0的新配置、新AOP支持、增强的IoC、JDBC和form标签等新功能。它通过实际完成一个完整的Spring项目示例,展示了与Spring相关API的使用技巧,能够显著减少每一位入门者...

Global site tag (gtag.js) - Google Analytics