Spring_Spring与AOP_AspectJ基于注解的AOP实现
一、AspectJ、Spring与AOP的关系
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。(百度百科)
Spring又将AspectJ的对于AOP的实现引入到自己的框架中。
在Spring中使用AOP开发时,一般使用AspectJ的实现方式。
二、AspectJ的通知类型
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
三、AspectJ的切入点表达式
表达式中加【】的部分表示可省略部分 ,个部分用空格分开。在其中可以使用以下符号:
execution(* * ..service.*.*(..))
指定所有包下的service子包下所有类(接口)中所有方法为切入点
execution(* *..ISomeService.*(..))
指定所有包下的ISomeService接口中所有方法为切入点
三、AspectJ的开发环境
导入2个Jar包
spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
四、AspectJ基于注解的AOP实现
1、前置通知
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //主业务接口 2 public interface ISomeService { 3 //目标方法 4 void doFirst(); 5 String doSecond(); 6 void doThird(); 7 8 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class SomeServiceImpl implements ISomeService { 2 3 @Override 4 public void doFirst() { 5 // TODO Auto-generated method stub 6 System.out.println("执行doFirst()方法"); 7 } 8 9 @Override 10 public String doSecond() { 11 // TODO Auto-generated method stub 12 System.out.println("执行doSecond()方法"); 13 return "abcde"; 14 } 15 16 @Override 17 public void doThird() { 18 // TODO Auto-generated method stub 19 System.out.println("执行doThird()方法"); 20 } 21 22 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import org.aspectj.lang.JoinPoint; 2 import org.aspectj.lang.annotation.Aspect; 3 import org.aspectj.lang.annotation.Before; 4 5 @Aspect //表示当前类为切面 6 public class MyAspect { 7 @Before("execution(* *..ISomeService.doFirst(..))") 8 public void before(){ 9 System.out.println("执行前置通知方法"); 10 } 11 12 @Before("execution(* *..ISomeService.doFirst(..))") 13 public void before(JoinPoint jp){ 14 System.out.println("执行前置通知方法 jp="+jp); 15 } 16 17 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import org.junit.Test; 2 import org.springframework.context.ApplicationContext; 3 import org.springframework.context.support.ClassPathXmlApplicationContext; 4 5 public class MyTest { 6 7 @Test 8 public void test01() { 9 //创建容器对象 10 String resource = "com/bjpowernode/annotation/applicationContext.xml"; 11 ApplicationContext ac=new ClassPathXmlApplicationContext(resource); 12 13 ISomeService service=(ISomeService) ac.getBean("someService"); 14 service.doFirst(); 15 System.out.println("--------------------"); 16 service.doSecond(); 17 System.out.println("--------------------"); 18 service.doThird(); 19 } 20 21 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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" xsi:schemaLocation=" 5 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 <!-- 注册切面 --> 10 <bean id="myAspect" class="com.bjpowernode.annotation.MyAspect"></bean> 11 12 <!-- 注册目标对象 --> 13 <bean id="someService" class="com.bjpowernode.annotation.SomeServiceImpl"></bean> 14 15 <!-- 注册AspectJ的自动代理 --> 16 <aop:aspectj-autoproxy/> 17 </beans>
输出:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
执行前置通知方法 执行前置通知方法 jp=execution(void com.bjpowernode.annotation.ISomeService.doFirst()) 执行doFirst()方法 -------------------- 执行doSecond()方法 -------------------- 执行doThird()方法
2.后置通知
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @AfterReturning("execution(* *..ISomeService.doSecond(..))") 2 public void myAfterReturning(){ 3 System.out.println("执行后置通知方法"); 4 5 } 6 7 @AfterReturning(value="execution(* *..ISomeService.doSecond(..))",returning="result") 8 public void myAfterReturning(Object result){ 9 System.out.println("执行后置通知方法 result="+result); 10 11 }
3、环绕通知
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @Around("execution(* *..ISomeService.doSecond(..))") 2 public Object myAround(ProceedingJoinPoint pjp) throws Throwable{ 3 System.out.println("执行环绕通知方法,目标方法执行之前"); 4 //执行目标方法 5 Object result = pjp.proceed(); 6 System.out.println("执行环绕通知方法,目标方法执行之后"); 7 return result; 8 9 }
输出:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 执行环绕通知方法,目标方法执行之前 2 执行doSecond()方法 3 执行环绕通知方法,目标方法执行之后
4、异常通知
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @AfterThrowing("execution(* *..ISomeService.doThird(..))") 2 public void myAfterThrowing(){ 3 System.out.println("执行异常通知方法"); 4 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @AfterThrowing(value="execution(* *..ISomeService.doThird(..))",throwing="ex") 2 public void myAfterThrowing(Exception ex){ 3 System.out.println("执行异常通知方法ex="+ex.getMessage()); 4 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 执行异常通知方法ex=/ by zero
5、最终通知
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @After("execution(* *..ISomeService.doThird(..))") 2 public void myAfter(){ 3 System.out.println("执行最终通知方法"); 4 }
五、定义切入点
定义了一个切入点,叫doThirdPointcut()
1 @After("doThirdPointcut()") 2 public void myAfter(){ 3 System.out.println("执行最终通知方法"); 4 } 5 //定义了一个切入点,叫doThirdPointcut() 6 @Pointcut("execution(* *..ISomeService.doThird(..))") 7 public void doThirdPointcut(){} 8 }