spring aop
aop相关support类介绍 https://www.cnblogs.com/dream-to-pku/p/5735293.html
advisor(切面) = advice + pointcut
MethodInceptor extends Interceptor extends Advice
- 声明一个advisor,比较常用AbstractPointcutAdvisor,可以参考aop.support包里各种advisor
- 实例化pointcut
- 实例化 advice 如MethodInceptor
- 把advisor放到配置类中
pointcut
常见的可以参考下方pointDemo以及更下面的切点类型介绍
通常pointcut的实现类中都有matches方法
- boolean matches(Method m, Class<?> targetClass)
- 用于匹配方法,和MethodMatcher 相关
- boolean matches(Class<?> clazz);
- 用于匹配类,和ClassFilter 相关
public interface Pointcut {
//返回一个ClassFilter
ClassFilter getClassFilter();
//返回一个MethodMatcher
MethodMatcher getMethodMatcher();
//TruePointCut,对应任何的方法都是匹配(总是匹配)
Pointcut TRUE = TruePointcut.INSTANCE;
}
public interface MethodInterceptor extends Interceptor {
@Nullable
Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;
}
Advisor Demo
可以参考DefaultBeanFactoryPointcutAdvisor extends AbstractBeanFactoryPointcutAdvisor
或者参考MethodSecurityMetadataSourceAdvisor
public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
private transient MethodInterceptor interceptor;
private final Pointcut pointcut = new MethodSecurityMetadataSourcePointcut();
}
Pointcut demo
@Test
public void testAspectJExpressionPointCut() throws NoSuchMethodException {
AspectJExpressionPointcut expressionPointcut = new AspectJExpressionPointcut();
//设置aspectj表达式,这个比较常用的表达式
expressionPointcut.setExpression("execution(* cn.tedu.demo.service.UserService.addUser(..))");
//匹配类
boolean b = expressionPointcut.matches(UserService.class);
//直接调用matches匹配方法
boolean a = expressionPointcut.matches(UserService.class.getDeclaredMethod("addUser", User.class), UserService.class);
System.out.println(a+"--->"+b);
}
@Test
public void testAnnotationMatchingPointcut() throws NoSuchMethodException {
//第一个参数是注解,第二参数表示是否在接口和父类的查找该注解
AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(Transactional.class, false);
//匹配方法上是否有@Transactional注解
boolean a = pointcut.getMethodMatcher().matches(UserService.class.getDeclaredMethod("addUser", User.class), UserService.class);
//匹配类上是否有@Transactional注解
boolean b = pointcut.getClassFilter().matches(UserService.class);
System.out.println(a+"--->"+b);
}
Advice Demo
- 可以参考下面的增强类型,应该就会MethodInterceptor和ThrowsAdvice就行了
AspectJ Demo
@Aspect
public class AnnotationAdvisor {
@Before("execution(* jiang.service.impl.UserServiceImpl.*(..))")
public void before() {
System.out.println("=======方法执行前========");
}
@After("execution(* jiang.service.impl.UserServiceImpl.*(..))")
public void after() {
System.out.println("=======注解方法执行后后后后========");
}
@Around("execution(* jiang.service.impl.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("======环绕前=====");
Signature signature = joinPoint.getSignature();
System.out.println(signature);
// 调用了这个,才会执行被代理对象相应的方法
joinPoint.proceed();
System.out.println("======环绕后=======");
}
}
创建增强类
Spring使用增强类定义横切逻辑,同时由于Spring只支持方法连接点,增强还包括了在方法的哪一点加入横切码的方位信息,所以增强既包含横向逻辑,又包含部分连接点的信息。
1.增强类型
AOP联盟为增强定义了org.aopalliance.aop.Advice接口,Spring支持5种类型的增强,安装增强在目标类方法的连接点设置
①:前置增强:org.springframework.aop.BeforeAdvice代表前置增强,因为Spring只支持方法级的增强,所以MethodBeforeAdvice是目前可用的前置增强,表示杂目标方法执行前实施增强而。
②:后置增强:org.springframework.aop.AfterReturningAdvice代表后增强,表示在目标方法执行后实施增强
③:环绕增强:org.aopalliance.intercept.MethodInterceptor代表环绕增强,表示在目标方法前后执行增强
④:异常抛出增强:org.springframework.aop.ThrowsAdvice代表抛出异常增强,表示在目标方法抛出异常后实施增强(事务)
⑤:引介增强:org.springframework.aop.IntroductionInterceptor代表引介增强,表示在目标类中添加一些新的方法和属性
切点
静态方法切点:
org.springframework.aop.support.StaticMethodMatcerPointcut是静态方法切点的抽象基类,默认情况下它匹配所有的类。StaticMethodMatcherPointcut包括两个主要的子类
分别是NameMatchMethodPointcut和AbstractRegexpMethodPointcut,前者提供简单字符串匹配方法前面,而后者使用正则表达式匹配方法前面。
注解切点:
org.springframework.aop.support.annotation.AnnotationMatchingPointcut实现类表示注解切点。
表达式切点:
org.springframework.aop.support.ExpressionPointcut接口主要是为了支持AspectJ切点表达式语法而定义的接口
流程切点:
org.springframework.aop.support.ControlFlowPointcut实现类表示控制流程切点。ControlFlowPointcut是一种特殊的切点,它根据程序执行堆栈的信息查看目标方法是否由某一个方法直接或间接发起调用,以此判断是否为匹配的连接点
复合切点:
org.springframework.aop.support.ComposablePointcut实现类是为了创建多个切点而提供的方便操作类,它所有的方法都返回ComposablePointcut类,这样就可以使用链接表达式对切点进行操作
切面类型
一般切面:Advisor代表一般切面,仅包含一个Advice,他本身就是一个简单的切面,只不过他代表的横切连接点是所有目标类的所有方法。
切点切面:PointcutAdvisor具有切点的切面,包含Advice和Pointcut两个类,这样就可以通过类,方法名以及方法方位等信息灵活地定义切面的连接点
引介切面:IntroductionAdvisor引介切面,引介切面是对应引介增强的特殊切面,它应用于类层面上,使用ClassFilter进行定义。