jar包依赖,除此以外还有spring依赖
maven依赖
<dependencies>
<!-- 有此依赖会远程下载其它相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.9.RELEASE</version>
</dependency>
<!-- aspectJ AOP 织入器 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
<context:component-scan base-package="">
<context:include-filter type="annotation"
expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
<aop:aspectj-autoproxy/>
@Before("execution(* 包名.*.*(..))")
示例代码
@Aspect
public class AuthAspect {
//定义切点
@Pointcut("execution(* com.cnblogs.hellxz.service.*.*(..))")
public void pointCut() {}
//前置处理
@Before("pointCut()")
public void auth() {
System.out.println("模拟权限检查……");
}
}
@Around("execution(* 包名.*(..))")
或使用切点@Around("pointcut()")
ProceedingJoinPoint
,必须有这个参数在切面方法的入参第一位示例代码
@Aspect
public class TxAspect {
//环绕处理
@Around("execution(* com.cnblogs.hellxz.service.*.*(..))")
Object auth(ProceedingJoinPoint point) {
Object object = null;
try {
System.out.println("事务开启……");
//放行
object = point.proceed();
System.out.println("事务关闭……");
} catch (Throwable e) {
e.printStackTrace();
}
return object;
}
}
虽然可以拿到返回值,但无法改变返回值
示例代码
@Aspect
public class AfterReturningAspect {
@AfterReturning(returning="rvt",
pointcut = "execution(* com.cnblogs.hellxz.service.*.*(..))")
//声明rvt时指定的类型会限定目标方法的返回值类型,必须返回指定类型或者没有返回值
//rvt类型为Object则是不对返回值做限制
public void log(Object rvt) {
System.out.println("获取目标返回值:"+ rvt);
System.out.println("假装在记录日志……");
}
/**
* 这个方法可以看出如果目标方法的返回值类型与切面入参的类型相同才会执行此切面方法
* @param itr
*/
@AfterReturning(returning="itr",
pointcut="execution(* com.cnblogs.hellxz.service.*.*(..))")
public void test(Integer itr) {
System.out.println("故意捣乱……:"+ itr);
}
}
@AfterReturning
类似,同样有一个切点和一个定义参数名的参数——throwing@AfterReturning
示例代码
@Aspect
public class AfterThrowingAspect {
@Pointcut("execution(* com.cnblogs.hellxz.test.*.*(..))")
public void pointcut() {}
/**
* 如果抛出异常在切面中的几个异常类型都满足,那么这几个切面方法都会执行
*/
@AfterThrowing(throwing="ex1",
pointcut="pointcut()")
//无论异常还是错误都会记录
//不捕捉错误可以使用Exception
public void throwing(Throwable ex1) {
System.out.println("出现异常:"+ex1);
}
@AfterThrowing(throwing="ex",
pointcut="pointcut()")
//只管IOException的抛出
public void throwing2(IOException ex) {
System.out.println("出现IO异常: "+ex);
}
}
pointcut定义的切点方法在@Before/@After/@Around需要写在双引号中,e.g. @Before("pointCut()")
Object[] getArgs()
:返回执行目标方法时的参数Signature getSignature()
:返回被增强方法的相关信息,e.g 方法名 etcObject getTarget()
:返回被织入增强处理的目标对象Object getThis()
:返回AOP框架目标对象生成的代理对象ProceedingJoinPoint是JoinPoint的子类,包含其所有方法外,还有两个公有方法
Object proceed()
:执行此方法才会执行目标方法Object proceed(Object[] args)
:执行此方法才会执行目标方法,而且会使用Object数组参数去代替实参,如果传入Object[]参数与方法入参数量不同或类型不同,会抛出异常
通过修改proceed方法的返回值来修改目标方法的返回值
优先级最高的会最先被织入,在退出连接点的时候,具有最高的优先级的最后被织入
当不同切面中两个增强处理切入同一连接点的时候,Spring AOP 会使用随机织入的方式
如果想要指定优先级,那么有两种方案:
org.springframework.core.Ordered
接口,实现getOrder方法,返回要指定的优先级@Order
修饰,指定一个优先级的值,值越小,优先级越高除了使用JoinPoint或ProceedingJoinPoint来获取目标方法的相关信息外(包括形参),如果只是简单访问形参,那么还有一种方法可以实现
&& args(arg0,arg1)
这种方式@Aspect
public class AccessInputArgs {
@Before("execution(* com.cnblogs.hellxz.test.*.*(..)) && args(arg0, arg1)")
public void access(String arg0, String arg1){
System.out.println("接收到的参数为arg0="+arg0+",arg1="+arg1);
}
}
注意:通过这种方式会只匹配到方法只有指定形参数量的方法,并且,在切面方法中指定的类型会限制目标方法,不符合条件的不会进行织入增强
通过定义切入点,我们可以复用切点,减少重复定义切点表达式等
切入点定义包含两个部分:
使用@Pointcut注解进行标记一个无参无返回值的方法,加上切点表达式
@Pointcut("execution(* com.cnblogs.hellxz.test.*.*(..))")
public void pointcut(){}
Spring AOP 支持10种切点指示符:execution、within、this、target、args、@target、@args、@within、@annotation、bean下面做下简记(没有写@Pointcut(),请注意):
execution: 用来匹配执行方法的连接点的指示符。
用法相对复杂,格式如下:execution(权限访问符 返回值类型 方法所属的类名包路径.方法名(形参类型) 异常类型)
e.g. execution(public String com.cnblogs.hellxz.test.Test.access(String,String))
权限修饰符和异常类型可省略,返回类型支持通配符,类名、方法名支持*通配,方法形参支持..通配
within: 用来限定连接点属于某个确定类型的类。
within(com.cnblogs.hellxz.test.Test)
within(com.cnblogs.hellxz.test.) //包下类
within(com.cnblogs.hellxz.test..) //包下及子包下
java @Pointcut("@args(org.springframework.web.bind.annotation.RequestBody)") public void methodsAcceptingEntities() {}
bean: 用于匹配指定Bean实例内的连接点,传入bean的id或name,支持使用*通配符
使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系
execution(* com.cnblogs.hellxz.test.*.*(..)) && args(arg0, arg1)
部分代码可以参考:我的Github
本文为学习总结,如需转载请注明出处
原文:https://www.cnblogs.com/hellxz/p/9629012.html