【Spring aop】Spring aop的XML和注解的两种配置实现

转载:http://blog.csdn.net/flysun3344/article/details/51679956

 

一:XML形式配置(传统aop联盟配置和AspectJ的aop配置)

[java] view plain copy
 
  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:p="http://www.springframework.org/schema/p"  
  5.     xmlns:context="http://www.springframework.org/schema/context"  
  6.     xmlns:aop="http://www.springframework.org/schema/aop"  
  7.     xsi:schemaLocation="  
  8.         http://www.springframework.org/schema/beans  
  9.         http://www.springframework.org/schema/beans/spring-beans.xsd  
  10.         http://www.springframework.org/schema/context  
  11.         http://www.springframework.org/schema/context/spring-context.xsd  
  12.         http://www.springframework.org/schema/aop  
  13.         http://www.springframework.org/schema/aop/spring-aop.xsd">  
  14.       
  15.     <!-- 切面类 -->  
  16.     <bean id="aop" class="cn.itcast.f_aop_xml.Aop"></bean>  
  17.       
  18.     <!-- Aop配置 -->  
  19.     <aop:config>  
  20.         <!-- 定义一个切入点表达式: 拦截哪些方法 -->  
  21.         <aop:pointcut expression="execution(* cn.itcast.f_aop_xml.*.*(..))" id="pt"/>  
  22.         <!-- 切面 -->  
  23.         <aop:aspect ref="aop">  
  24.             <!-- 环绕通知 -->  
  25.             <aop:around method="around" pointcut-ref="pt"/>  
  26.             <!-- 前置通知: 在目标方法调用前执行 -->  
  27.             <aop:before method="begin" pointcut-ref="pt"/>  
  28.             <!-- 后置通知: -->  
  29.             <aop:after method="after" pointcut-ref="pt"/>  
  30.             <!-- 返回后通知 -->  
  31.             <aop:after-returning method="afterReturning" pointcut-ref="pt"/>  
  32.             <!-- 异常通知 -->  
  33.             <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>  
  34.               
  35.         </aop:aspect>  
  36.     </aop:config>  
  37. </beans>  

注意对切面的配置有两种方式:一种是传统的aop联盟制定的aop通知的配置,一种是spring支持的AspectJ框架的切面

切入点表达式有如下形式:

[java] view plain copy
 
  1. <!-- 定义一个切入点表达式: 拦截哪些方法 -->  
  2.         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>-->  
  3.           
  4.         <!-- 【拦截所有public方法】 -->  
  5.         <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->  
  6.           
  7.         <!-- 【拦截所有save开头的方法 】 -->  
  8.         <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->  
  9.           
  10.         <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->  
  11.         <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->  
  12.           
  13.         <!-- 【拦截指定类的所有方法】 -->  
  14.         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->  
  15.           
  16.         <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->  
  17.         <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->  
  18.           
  19.         <!-- 【多个表达式】 -->  
  20.         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->  
  21.         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->  
  22.         <!-- 下面2个且关系的,没有意义 -->  
  23.         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->  
  24.         <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->  
  25.           
  26.         <!-- 【取非值】 -->  
  27.         <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->  
  28.         <aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>  
  29.           

切面类如下

[java] view plain copy
 
  1. // 切面类  
  2. public class Aop {  
  3.       
  4.     public void begin(){  
  5.         System.out.println("开始事务/异常");  
  6.     }  
  7.       
  8.     public void after(){  
  9.         System.out.println("提交事务/关闭");  
  10.     }  
  11.       
  12.     public void afterReturning() {  
  13.         System.out.println("afterReturning()");  
  14.     }  
  15.       
  16.     public void afterThrowing(){  
  17.         System.out.println("afterThrowing()");  
  18.     }  
  19.       
  20.     public void around(ProceedingJoinPoint pjp) throws Throwable{  
  21.         System.out.println("环绕前....");  
  22.         pjp.proceed();  // 执行目标方法  
  23.         System.out.println("环绕后....");  
  24.     }  
  25.       
  26. }  

调用的接口如下

[java] view plain copy
 
  1. public class UserDao implements IUserDao{  
  2.   
  3.     @Override  
  4.     public void save() {  
  5.         System.out.println("-----核心业务:保存!!!------");   
  6.     }  
  7. }  

测试类如下

[java] view plain copy
 
  1. public class App {  
  2.       
  3.     ApplicationContext ac =   
  4.         new ClassPathXmlApplicationContext("cn/itcast/f_aop_xml/bean.xml");  
  5.   
  6.     // 目标对象有实现接口,spring会自动选择“JDK代理”  
  7.     @Test  
  8.     public void testApp() {  
  9.         IUserDao userDao = (IUserDao) ac.getBean("userDao");  
  10.         System.out.println(userDao.getClass());//$Proxy001    
  11.         userDao.save();  
  12.     }  
  13.       
  14.     // 目标对象没有实现接口, spring会用“cglib代理”  
  15.     @Test  
  16.     public void testCglib() {  
  17.         OrderDao orderDao = (OrderDao) ac.getBean("orderDao");  
  18.         System.out.println(orderDao.getClass());  
  19.         orderDao.save();  
  20.     }  
  21. }  
 
上面的xml的配置主要是针对aspectJ框架支持的切面的配置。当前aop的配置基本上都用上面这种形式的配置。这里也简单介绍下传统的aop联盟定义的通知的配置方法,仅仅作为了解即可。aop联盟定义了五种通知类型如下:
我们在aop编程时需要自定义通知类,实现上面的五种通知就可以了;例子如下:
传统aop联盟配置方式一如下:
传统aop联盟配置方式二:只需将上面的<aop:config>替换为BeanNameAutoProxyCreator的配置即可,如下:

二:注解形式配置

配置文件
[java] view plain copy
 
  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:p="http://www.springframework.org/schema/p"  
  5.     xmlns:context="http://www.springframework.org/schema/context"  
  6.     xmlns:aop="http://www.springframework.org/schema/aop"  
  7.     xsi:schemaLocation="  
  8.         http://www.springframework.org/schema/beans  
  9.         http://www.springframework.org/schema/beans/spring-beans.xsd  
  10.         http://www.springframework.org/schema/context  
  11.         http://www.springframework.org/schema/context/spring-context.xsd  
  12.         http://www.springframework.org/schema/aop  
  13.         http://www.springframework.org/schema/aop/spring-aop.xsd">  
  14.       
  15.     <!-- 开启注解扫描 -->  
  16.     <context:component-scan base-package="cn.itcast.e_aop_anno"></context:component-scan>  
  17.       
  18.     <!-- 开启aop注解方式 -->  
  19.     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>  
  20. </beans>     

切面类如下;
[java] view plain copy
 
  1. @Component  
  2. @Aspect  // 指定当前类为切面类  
  3. public class Aop {  
  4.   
  5.     // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象  
  6.       
  7.     @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))")  
  8.     public void pointCut_(){  
  9.     }  
  10.       
  11.     // 前置通知 : 在执行目标方法之前执行  
  12.     @Before("pointCut_()")  
  13.     public void begin(){  
  14.         System.out.println("开始事务/异常");  
  15.     }  
  16.       
  17.     // 后置/最终通知:在执行目标方法之后执行  【无论是否出现异常最终都会执行】  
  18.     @After("pointCut_()")  
  19.     public void after(){  
  20.         System.out.println("提交事务/关闭");  
  21.     }  
  22.       
  23.     // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】  
  24.     @AfterReturning("pointCut_()")  
  25.     public void afterReturning() {  
  26.         System.out.println("afterReturning()");  
  27.     }  
  28.       
  29.     // 异常通知: 当目标方法执行异常时候执行此关注点代码  
  30.     @AfterThrowing("pointCut_()")  
  31.     public void afterThrowing(){  
  32.         System.out.println("afterThrowing()");  
  33.     }  
  34.       
  35.     // 环绕通知:环绕目标方式执行  
  36.     @Around("pointCut_()")  
  37.     public void around(ProceedingJoinPoint pjp) throws Throwable{  
  38.         System.out.println("环绕前....");  
  39.         pjp.proceed();  // 执行目标方法  
  40.         System.out.println("环绕后....");  
  41.     }  
  42.       
  43. }  

接口类如下:
[java] view plain copy
 
  1. @Component   // 加入容器  
  2. public class UserDao implements IUserDao{  
  3.   
  4.     @Override  
  5.     public void save() {  
  6.         System.out.println("-----核心业务:保存!!!------");   
  7.     }  
  8. }  

测试类如下:
同一种的测试类
原文地址:https://www.cnblogs.com/songjy2116/p/7865633.html