最全面的 Spring事务管理和AOP切面日志的注入 —aop:pointcut expression解析

先来看看这个spring的配置文件的配置:

 

  <!-- 事务管理器 -->
 <bean id="transactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
 </bean>


 <!-- 配置事务的传播特性 -->
 <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
   <tx:method name="get*" propagation="REQUIRED" read-only="true" />
   <tx:method name="del*" propagation="REQUIRED" />
   <tx:method name="save*" propagation="REQUIRED" />
   <tx:method name="update*" propagation="REQUIRED" />
  </tx:attributes>
 </tx:advice>


 <!-- 配置事务拦截器拦截哪些类的哪些方法,一般设置成拦截Service -->
 <aop:config>
  <aop:pointcut expression="execution(* com.xy.service.*.*(..))"
   id="allDaoMethod" />
  <aop:advisor advice-ref="txAdvice" pointcut-ref="allDaoMethod" />
 </aop:config>


表示com.xy.service包下的所有方法为为事务管理。

 

execution(* com.aptech.jb.epet.dao.hibimpl.*.*(..)) 

 

这样写应该就可以了 这是com.aptech.jb.epet.dao.hibimpl 包下所有的类的所有方法。。

第一个*代表所有的返回值类型 

第二个*代表所有的类

第三个*代表类所有方法 最后一个..代表所有的参数。

 

 

下面给出一些常见切入点表达式的例子:

  • 任意公共方法的执行:

    execution(public * *(..))
    
  • 任何一个以“set”开始的方法的执行:

    execution(* set*(..))
    
  • AccountService 接口的任意方法的执行:

    execution(* com.xyz.service.AccountService.*(..))
    
  • 定义在service包里的任意方法的执行:

    execution(* com.xyz.service.*.*(..))
    
  • 定义在service包或者子包里的任意类的任意方法的执行:

    execution(* com.xyz.service..*.*(..))
    
 
原帖地址:http://hane00.blog.163.com/blog/static/160061522011427473965/
AOP的理解 

         1、AOP的概述 
                   AOP是一种不同于OOP(面向对象编程)的编程模式,它不是OOP的替代,而是对OOP的一种有益补充。 
         2、spring AOP的原理 
         3、spring AOP的实现 
                   在spring2.5中,常用的AOP实现方式有两种。第一种是基于xml配置文件方式的实现,第二种是基于注解方式的实现。 
                   接下来,以具体的是理智讲解这两种方式的使用。 

Java代码   
package com.zxf.service;   
    
 /**  
 * 业务逻辑接口  
* @author z_xiaofei168  
 */   
 public interface AccountService {   
     public void save(String loginname, String password);   
 }   
    
它的实现类   
    
package com.zxf.service;   
 import com.zxf.dao.AccountDao;   
    
 /**  
 * AccountService的实现类  
* @author z_xiaofei168  
 */   
 public class AccountServiceImpl implements AccountService {   
     private  AccountDao accountDao;   
        
     public AccountServiceImpl() {}   
        
     /** 带参数的构造方法 */   
     public AccountServiceImpl(AccountDao accountDao){   
         this.accountDao = accountDao;   
     }   
        
     public void save(String loginname, String password) {   
         accountDao.save(loginname, password);   
         throw new RuntimeException("故意抛出一个异常。。。。");   
     }   
        
     /** set方法 */   
     public void setAccountDao(AccountDao accountDao) {   
         this.accountDao = accountDao;   
     }   
 }   
     
      对于业务系统来说,AccountServiceImpl类就是目标实现类,它的业务方法,如save()方法的前后或代码会出现异常的地方都是AOP的连接点。 

 下面是日志服务类的代码: 


Java代码   
package com.zxf.aspect;   
    
 import org.aspectj.lang.JoinPoint;   
 import org.aspectj.lang.ProceedingJoinPoint;   
    
 /**  
 * 日志切面类  
* @author z_xiaofei168  
 */   
 public class LogAspect {   
    
     //任何通知方法都可以将第一个参数定义为 org.aspectj.lang.JoinPoint类型    
     public void before(JoinPoint call) {   
         //获取目标对象对应的类名   
         String className = call.getTarget().getClass().getName();   
         //获取目标对象上正在执行的方法名   
         String methodName = call.getSignature().getName();   
            
         System.out.println("前置通知:" + className + "类的" + methodName + "方法开始了");   
     }   
        
     public void afterReturn() {   
         System.out.println("后置通知:方法正常结束了");   
     }   
        
     public void after(){   
         System.out.println("最终通知:不管方法有没有正常执行完成,一定会返回的");   
     }   
        
     public void afterThrowing() {   
         System.out.println("异常抛出后通知:方法执行时出异常了");   
     }   
        
     //用来做环绕通知的方法可以第一个参数定义为org.aspectj.lang.ProceedingJoinPoint类型   
     public Object doAround(ProceedingJoinPoint call) throws Throwable {   
         Object result = null;   
         this.before(call);//相当于前置通知   
         try {   
             result = call.proceed();   
             this.afterReturn(); //相当于后置通知   
         } catch (Throwable e) {   
    
             this.afterThrowing();  //相当于异常抛出后通知   
             throw e;   
         }finally{   
             this.after();  //相当于最终通知   
         }   
            
         return result;   
     }   
 }   

      这个类属于业务服务类,如果用AOP的术语来说,它就是一个切面类,它定义了许多通知。Before()、afterReturn()、after()和afterThrowing()这些方法都是通知。 

<1>.基于xml配置文件的AOP实现 

         这种方式在实现AOP时,有4个步骤。 

Xml代码   
< ?xml version="1.0" encoding="UTF-8"?>   
< beans xmlns="http://www.springframework.org/schema/beans"   
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
         xmlns:aop="http://www.springframework.org/schema/aop"   
         xsi:schemaLocation="   
             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>   
    
     <bean id="accountDaoImpl" class="com.zxf.dao.AccountDaoImpl"/>   
        
     <bean id="accountService" class="com.zxf.service.AccountServiceImpl">   
         <property name=" accountDaoImpl " ref=" accountDaoImpl "/>   
     </bean>   
    
     <!-- 日志切面类 -->   
     <bean id="logAspectBean" class="com.zxf.aspect.LogAspect"/>   
        
     <!-- 第1步: AOP的配置 -->   
     <aop:config>   
         <!-- 第2步:配置一个切面 -->   
         <aop:aspect id="logAspect" ref="logAspectBean">   
             <!-- 第3步:定义切入点,指定切入点表达式 -->   
             <aop:pointcut id="allMethod"    
                 expression="execution(* com.zxf.service.*.*(..))"/>   
                    
             <!-- 第4步:应用前置通知 -->   
             <aop:before method="before" pointcut-ref="allMethod" />   
             <!-- 第4步:应用后置通知 -->   
             <aop:after-returning method="afterReturn" pointcut-ref="allMethod"/>   
             <!-- 第4步:应用最终通知 -->   
             <aop:after method="after" pointcut-ref="allMethod"/>   
             <!-- 第4步:应用抛出异常后通知 -->   
             <aop:after-throwing method="afterThrowing" pointcut-ref="allMethod"/>   
                
             <!-- 第4步:应用环绕通知 -->   
             <!--   
             <aop:around method="doAround" pointcut-ref="allMethod" />  
              -->   
         </aop:aspect>   
     </aop:config>   
< /beans>   


     上述配置针对切入点应用了前置、后置、最终,以及抛出异常后通知。这样在测试执行AccountServiceImpl类的save()方法时,控制台会有如下结果输出。 

 前置通知:com.zxf.service.AccountServiceImpl类的save方法开始了。 
 针对MySQL的AccountDao实现中的save()方法。 
 后置通知:方法正常结束了。 
 最终通知:不管方法有没有正常执行完成,一定会返回的。 
   <2>基于注解的AOP的实现 

    首先创建一个用来作为切面的类LogAnnotationAspect,同时把这个类配置在spring的配置文件中。 
        在spring2.0以后引入了JDK5.0的注解Annotation的支持,提供了对AspectJ基于注解的切面的支持,从而 更进一步地简化AOP的配置。具体的步骤有两步。 

Spring的配置文件是如下的配置: 


Xml代码   
< ?xml version="1.0" encoding="UTF-8"?>   
< beans xmlns="http://www.springframework.org/schema/beans"   
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
         xmlns:aop="http://www.springframework.org/schema/aop"   
         xsi:schemaLocation="   
             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>   
    
     <bean id="accountDao" class="com.zxf.dao.AccountDaoImpl"/>   
     <bean id="accountService" class="com.zxf.service.AccountServiceImpl">   
         <property name="accountDao" ref="accountDao"/>   
     </bean>   
     <!-- 把切面类交由Spring容器来管理 -->   
     <bean id="logAspectBean" class="com.zxf.aspect.LogAnnotationAspect"/>   
     <!-- 启用spring对AspectJ注解的支持 -->   
     <aop:aspectj-autoproxy/>   
< /beans>   

这是那个切面的类LogAnnotationAspect 
 Java代码   
package com.zxf.aspect;   
    
 import org.aspectj.lang.JoinPoint;   
 import org.aspectj.lang.ProceedingJoinPoint;   
 import org.aspectj.lang.annotation.After;   
 import org.aspectj.lang.annotation.AfterReturning;   
 import org.aspectj.lang.annotation.AfterThrowing;   
 import org.aspectj.lang.annotation.Aspect;   
 import org.aspectj.lang.annotation.Before;   
 import org.aspectj.lang.annotation.Pointcut;   
    
 /**  
 * 日志切面类  
*/   
 @Aspect  //定义切面类   
public class LogAnnotationAspect {   
     @SuppressWarnings("unused")   
     //定义切入点   
     @Pointcut("execution(* com.zxf.service.*.*(..))")   
     private void allMethod(){}   
        
     //针对指定的切入点表达式选择的切入点应用前置通知   
     @Before("execution(* com. zxf.service.*.*(..))")   
     public void before(JoinPoint call) {   
            
         String className = call.getTarget().getClass().getName();   
         String methodName = call.getSignature().getName();   
            
         System.out.println("【注解-前置通知】:" + className + "类的"    
                 + methodName + "方法开始了");   
     }   
     //访问命名切入点来应用后置通知   
     @AfterReturning("allMethod()")   
     public void afterReturn() {   
         System.out.println("【注解-后置通知】:方法正常结束了");   
     }   
        
     //应用最终通知   
     @After("allMethod()")   
     public void after(){   
         System.out.println("【注解-最终通知】:不管方法有没有正常执行完成,"    
                 + "一定会返回的");   
     }   
        
     //应用异常抛出后通知   
     @AfterThrowing("allMethod()")   
     public void afterThrowing() {   
         System.out.println("【注解-异常抛出后通知】:方法执行时出异常了");   
     }   
        
     //应用周围通知   
     //@Around("allMethod()")   
     public Object doAround(ProceedingJoinPoint call) throws Throwable{   
         Object result = null;   
         this.before(call);//相当于前置通知   
         try {   
             result = call.proceed();   
             this.afterReturn(); //相当于后置通知   
         } catch (Throwable e) {   
             this.afterThrowing();  //相当于异常抛出后通知   
             throw e;   
         }finally{   
             this.after();  //相当于最终通知   
         }   
            
         return result;   
     }   
 }

你可能感兴趣的:(最全面的 Spring事务管理和AOP切面日志的注入 —aop:pointcut expression解析)