spring中基于Aspectj的AOP学习笔记
使用Aspectj实现AOP
–注解方式
–xml方式
Aspectj是一个基于java语言的AOP框架
环境准备
导入spring aop和aspectj相关的jar包这里直接在pom.xml中引入坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
spring中的配置
注解方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启Aspectj自动代理-->
<aop:aspectj-autoproxy/>
<!--定义目标类-->
<bean id="productDao" class="com.aspectj.demo1.ProductDao"/>
<!--定义切面类-->
<bean id="myAspect" class="com.aspectj.demo1.MyAspectAnno"/>
</beans>
项目结构
目标类
package com.aspectj.demo1;
//目标类
public class ProductDao {
public void add(){
System.out.println("保存用户信息...");
}
public String delete(){
System.out.println("删除用户信息...");
return "返回值";
}
public void update(){
System.out.println("修改用户信息...");
}
public void findOne(){
System.out.println("查询单个用户信息...");
}
public void findAll(){
System.out.println("查询所有用户信息...");
}
}
@Aspectj提供的不同通知类型
@Before前置通知,在被增强的方法之前执行,相当与BeforAdvice
@AfterReturning后置通知,在被增强的方法之后执行,可以有返回值,相当与AfterRetruningAdvice
@Around环绕通知,在被增强的方法前后各执行一次,相当与MethodInterceptor
@AfterThrowing异常抛出通知,在被增强的方法发生异常时执行,相当于ThrowAdvice
@After最终final通知,不管是否有异常该方法都会执行
在通知中通过value属性定义切点
为目标类定义切面类
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
//切面类
@Aspect
public class MyAspectAnno {
//要增强的代码
@Before(value = "execution(* com.aspectj.demo1.ProductDao.add())")
public void before(JoinPoint joinPoint){
System.out.println("前置通知===="+joinPoint);
}
@AfterReturning(value = "execution(* com.aspectj.demo1.ProductDao.delete())",returning = "result")
public void afterReturning(Object result){
//result被增强方法的返回值,可以作为参数
System.out.println("后置通知===="+result);
}
@Around(value = "execution(* com.aspectj.demo1.ProductDao.update())")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前通知=====");
Object obj = joinPoint.proceed();//执行目标方法,如果不写目标方法就不被执行
System.out.println("环绕后通知=====");
return obj;//返回值为目标方法
}
@AfterThrowing(value = "execution(* com.aspectj.demo1.ProductDao.*(..))",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常通知===="+e.getMessage());
}
@After(value = "execution(* com.aspectj.demo1.ProductDao.findAll())")
public void after(){
System.out.println("最终通知,即使被增强的方法出现了异常,我也执行");
}
}
结果如下
为了方便还可以这样写
package com.aspectj.demo1;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
//切面类
//@Aspect
public class MyAspectAnno {
//要增强的代码
@Before(value = "myPointCut1()")
public void before(JoinPoint joinPoint){
System.out.println("前置通知===="+joinPoint);
}
@AfterReturning(value = "myPointCut2()")
public void afterReturning(Object result){//result被增强方法的返回值
System.out.println("后置通知===="+result);
}
@Around(value = "myPointCut3()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前通知=====");
Object obj = joinPoint.proceed();//执行目标方法
System.out.println("环绕后通知=====");
return obj;//返回值为目标方法
}
@AfterThrowing(value = "myPointCut4()",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常通知===="+e.getMessage());
}
@After(value = "myPointCut5()")
public void after(){
System.out.println("最终通知,即使被增强的方法出现了异常,我也执行");
}
@Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.add())")
private void myPointCut1(){}
@Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.delete())")
private void myPointCut2(){}
@Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.update())")
private void myPointCut3(){}
@Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.findOne())")
private void myPointCut4(){}
@Pointcut(value = "execution(* com.aspectj.demo1.ProductDao.findAll())")
private void myPointCut5(){}
}
XML的配置方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启Aspectj自动代理-->
<!--<aop:aspectj-autoproxy/>-->
<!--定义目标类-->
<bean id="productDao" class="com.aspectj.demo1.ProductDao"/>
<!--定义切面类-->
<bean id="myAspect" class="com.aspectj.demo1.MyAspectAnno"/>
<!--基于XML的方式-->
<!--aop的配置-->
<aop:config>
<!--定义切入点:哪些类的哪些方法需要增强-->
<aop:pointcut id="myPointCut1" expression="execution(* com.aspectj.demo1.ProductDao.add())"/>
<aop:pointcut id="myPointCut2" expression="execution(* com.aspectj.demo1.ProductDao.delete())"/>
<aop:pointcut id="myPointCut3" expression="execution(* com.aspectj.demo1.ProductDao.update())"/>
<aop:pointcut id="myPointCut4" expression="execution(* com.aspectj.demo1.ProductDao.findOne())"/>
<aop:pointcut id="myPointCut5" expression="execution(* com.aspectj.demo1.ProductDao.findAll())"/>
<!--配置切面-->
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="myPointCut1"/>
<aop:after-returning method="afterReturning" pointcut-ref="myPointCut2" returning="result"/>
<aop:around method="around" pointcut-ref="myPointCut3" />
<aop:after-throwing method="afterThrowing" pointcut-ref="myPointCut4" throwing="e"/>
<aop:after method="after" pointcut-ref="myPointCut5"/>
</aop:aspect>
</aop:config>
</beans>