前言:
在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习.
一, AspectJ的概述:
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
Spring为了简化自身的AOP的开发,将AspectJ拿过来作为Spring自身一个AOP的开发.
二, Spring AspectJ开发实例
2.1 开发所需jar包
2.2 AspectJ 注解开发规范
2.2.1 @AspectJ提供不同的通知类型
@Before 前置通知,相当于BeforeAdvice
在执行目标方法之前完成一个操作,获得到切入点信息.
@AfterReturning 后置通知,相当于AfterReturningAdvice
1 在目标方法执行之后完成一个操作,获得方法的返回值. 2 3 @AfterReturning(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.update(..))",returning="result") 4 public void afterReturing(Object result){ 5 System.out.println("后置通知============"+result); 6 }
@Around 环绕通知,相当于MethodInterceptor
1 在目标方法执行的前和执行后完成一个操作,阻止目标方法执行. 2 3 @Around(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.delete(..))") 4 public Object around(ProceedingJoinPoint joinPoint) throws Throwable{ 5 System.out.println("环绕前通知=========="); 6 Object obj = joinPoint.proceed(); 7 System.out.println("环绕后通知=========="); 8 return obj; 9 }
@AfterThrowing抛出通知,相当于ThrowAdvice
1 在目标方法出现异常的时候,完成一个操作.获得异常信息. 2 3 @AfterThrowing(value="execution(* cn.itcast.aspectj.demo1.CustomerService+.find(..))",throwing="e") 4 public void afterThrowing(Throwable e){ 5 System.out.println("异常抛出通知========="+e.getMessage()); 6 }
@After 最终final通知,不管是否异常,该通知都会执行
1 在目标方法任何情况下都会执行的操作.相当于finally中的代码. 2 3 @After(value="execution(* cn.itcast.aspectj.demo1.CustomerService+.find(..))") 4 public void after(){ 5 System.out.println("最终通知==========="); 6 }
2.2.2 通过配置启用@AspectJ切面
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.xsd 7 http://www.springframework.org/schema/aop 8 http://www.springframework.org/schema/aop/spring-aop.xsd"> 9 <!-- 开启AspectJ自动代理--> 10 <aop:aspectj-autoproxy /> 11 </beans>
2.2.3 在通知中通过value属性定义切点
通过execution函数,可以定义切点的方法切入
语法:
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
例如
匹配所有类public方法 execution(public * *(..))
匹配指定包下所有类方法 execution(* cn.itcast.dao.*(..)) 不包含子包
execution(* cn.itcast.dao..*(..)) ..*表示包、子孙包下所有类
匹配指定类所有方法 execution(* cn.itcast.service.UserService.*(..))
匹配实现特定接口所有类方法 execution(* cn.itcast.dao.GenericDAO+.*(..))
匹配所有save开头的方法 execution(* save*(..))
2.2.4 AspectJ的切入点:
1 统一管理切入点的表达式. 2 @Pointcut(value="execution(* cn.itcast.aspectj.demo1.CustomerService+.find(..))") 3 private void myPointcut1(){} //这个类没有实际用途, 只是为了@Pointcut 注解
2.2.6 Aspect和Advisor的区别:
Advisor :传统的切面.传统切面一般都是由一个切入点和一个通知的组合.
Aspect :真正意义上的切面.由多个切入点和多个通知的组合.
2.3 Spring AspctJ 基于注解模式的开发
CustomerService.java:
1 public interface CustomerService { 2 3 public void save(); 4 public Integer update(); 5 public void delete(); 6 public void find(); 7 }
CustomerServiceImpl.java:
1 public class CustomerServiceImpl implements CustomerService { 2 3 @Override 4 public void save() { 5 System.out.println("保存客户..."); 6 } 7 8 @Override 9 public Integer update() { 10 System.out.println("修改客户..."); 11 return 100; 12 } 13 14 @Override 15 public void delete() { 16 System.out.println("删除客户..."); 17 } 18 19 @Override 20 public void find() { 21 System.out.println("查询客户..."); 22 int d = 1 / 0; 23 } 24 25 }
MyAspectAnno.java:
1 /** 2 * 自定义切面类: 3 * 4 */ 5 @Aspect 6 public class MyAspectAnno { 7 8 @Before(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.save(..))") 9 public void before(JoinPoint joinPoint){ 10 System.out.println("前置通知============"+joinPoint); 11 } 12 13 @AfterReturning(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.update(..))",returning="result") 14 public void afterReturing(Object result){ 15 System.out.println("后置通知============"+result); 16 } 17 18 @Around(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.delete(..))") 19 public Object around(ProceedingJoinPoint joinPoint) throws Throwable{ 20 System.out.println("环绕前通知=========="); 21 Object obj = joinPoint.proceed(); 22 System.out.println("环绕后通知=========="); 23 return obj; 24 } 25 26 @AfterThrowing(value="MyAspectAnno.myPointcut1()",throwing="e") 27 public void afterThrowing(Throwable e){ 28 System.out.println("异常抛出通知========="+e.getMessage()); 29 } 30 31 @After(value="MyAspectAnno.myPointcut1()") 32 public void after(){ 33 System.out.println("最终通知==========="); 34 } 35 36 @Pointcut(value="execution(* cn.augmentum.aspectj.demo1.CustomerService+.find(..))") 37 private void myPointcut1(){} 38 }
SpringDemo.java 测试类:
1 @RunWith(SpringJUnit4ClassRunner.class) 2 @ContextConfiguration("classpath:applicationContext.xml") 3 public class SpringDemo1 { 4 5 @Resource(name = "customerService") 6 private CustomerService customerService; 7 8 @Test 9 public void demo1() { 10 customerService.save(); 11 customerService.update(); 12 customerService.delete(); 13 customerService.find(); 14 } 15 }
applicationContext.xml 配置文件:
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=" 6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 8 9 <!-- 使用注解完成AOP的开发 --> 10 <aop:aspectj-autoproxy/> 11 12 <!-- 目标对象 --> 13 <bean id="customerService" class="cn.augmentum.aspectj.demo1.CustomerServiceImpl"/> 14 15 <!-- 配置切面 --> 16 <bean id="myAspectAnno" class="cn.augmentum.aspectj.demo1.MyAspectAnno"/> 17 </beans>
2.3 Spring AspctJ 基于xml模式的开发
OrderService.java:
1 public class OrderService { 2 public void save(){ 3 System.out.println("保存订单..."); 4 } 5 public Integer update(){ 6 System.out.println("修改订单..."); 7 return 200; 8 } 9 public void delete(){ 10 System.out.println("删除订单..."); 11 } 12 public void find(){ 13 System.out.println("查询订单..."); 14 //int d = 1/ 0; 15 } 16 }
MyAspectXml.java:
1 public class MyAspectXml { 2 3 public void before(){ 4 System.out.println("前置通知==========="); 5 } 6 7 public void afterReturing(Object result){ 8 System.out.println("后置通知==========="+result); 9 } 10 11 public Object around(ProceedingJoinPoint joinPoint) throws Throwable{ 12 System.out.println("环绕前通知=========="); 13 Object obj = joinPoint.proceed(); 14 System.out.println("环绕后通知=========="); 15 return obj; 16 } 17 18 public void afterThrowing(Throwable e){ 19 System.out.println("异常抛出通知========"+e.getMessage()); 20 } 21 22 public void after(){ 23 System.out.println("最终通知=========="); 24 } 25 }
SpringDemo.java 测试类:
1 @RunWith(SpringJUnit4ClassRunner.class) 2 @ContextConfiguration("classpath:applicationContext.xml") 3 public class SpringDemo2 { 4 5 @Resource(name="orderService") 6 private OrderService orderService; 7 8 @Test 9 public void demo1(){ 10 orderService.save(); 11 orderService.update(); 12 orderService.delete(); 13 orderService.find(); 14 } 15 }
applicationContext.xml 配置文件:
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=" 6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 8 9 <!-- 配置目标类 --> 10 <bean id="orderService" class="cn.augmentum.aspectj.demo2.OrderService"></bean> 11 12 <!-- 配置切面 --> 13 <bean id="myAspectXml" class="cn.augmentum.aspectj.demo2.MyAspectXml"></bean> 14 15 <!-- AOP的配置 --> 16 <aop:config> 17 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.save(..))" id="pointcut1"/> 18 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.update(..))" id="pointcut2"/> 19 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.delete(..))" id="pointcut3"/> 20 <aop:pointcut expression="execution(* cn.augmentum.aspectj.demo2.OrderService.find(..))" id="pointcut4"/> 21 <aop:aspect ref="myAspectXml"> 22 <aop:before method="before" pointcut-ref="pointcut1"/> 23 <aop:after-returning method="afterReturing" pointcut-ref="pointcut2" returning="result"/> 24 <aop:around method="around" pointcut-ref="pointcut3"/> 25 <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e"/> 26 <aop:after method="after" pointcut-ref="pointcut4"/> 27 </aop:aspect> 28 </aop:config> 29 </beans>
OK. 到了这里Spring 基于AOP的开发也总结完了, 学习之路漫漫, 谨以此记录成长的过程!