java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring AOP切点表达式

Spring AOP切点表达式使用及说明

作者:ZerahMu

这篇文章主要介绍了Spring AOP切点表达式使用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

切点表达式

在Spring AOP中,连接点始终代表方法的执行。切入点是与连接点匹配的谓词,切入点表达语言是以编程方式描述切入点的方式。

切点表达式是除过AOP逻辑之外我们开发主要关注的东西,本小结对各种表达式作以说明,spring aop中目前有9种切入点表达式的写法

一、execute表达式

拦截任意公共方法

execution(public * *(..))

拦截以set开头的任意方法

execution(* set*(..))

拦截类或者接口中的方法

拦截AccountService(类、接口)中定义的所有方法
execution(* com.xyz.service.AccountService.*(..))

拦截包中定义的方法,不包含子包中的方法

拦截com.xyz.service包中所有类中任意方法,**不包含**子包中的类
execution(* com.xyz.service.*.*(..))

拦截包或者子包中定义的方法

拦截com.xyz.service包或者子包中定义的所有方法
execution(* com.xyz.service..*.*(..))

二、within表达式

表达式格式:包名.* 或者 包名…*

拦截包中任意方法,不包含子包中的方法

拦截service包中任意类的任意方法
within(com.xyz.service.*)

拦截包或者子包中定义的方法

拦截service包及子包中任意类的任意方法
within(com.xyz.service..*)

三、this表达式

代理对象为指定的类型会被拦截

目标对象使用aop之后生成的代理对象必须是指定的类型才会被拦截,注意是目标对象被代理之后生成的代理对象和指定的类型匹配才会被拦截
this(com.xyz.service.AccountService)

this表达式的使用,可能不是很好理解,借用示例说明一下:

package com.ms.aop.jthis.demo1;
​
public interface IService {
    void m1();
}

package com.ms.aop.jthis.demo1;
​
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
​
@Slf4j
@Component
public class ServiceImpl implements IService {
    @Override
    public void m1() {
        log.info("切入点this测试!");
    }
}

package com.ms.aop.jthis.demo1;
​
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class Interceptor1 {
​
    @Pointcut("this(com.ms.aop.jthis.demo1.ServiceImpl)")
    public void pointcut() {
    }
​
    @Around("pointcut()")
    public Object invoke(ProceedingJoinPoint invocation) throws Throwable {
        log.info("方法执行之前");
        Object result = invocation.proceed();
        log.info("方法执行完毕");
        return result;
    }
}

package com.ms.aop.jthis.demo1;
​
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
​
@ComponentScan(basePackageClasses = {Client.class})
@EnableAspectJAutoProxy
@Slf4j
public class Client {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Client.class);
        IService service = annotationConfigApplicationContext.getBean(IService.class);
        service.m1();
        log.info("{}", service instanceof ServiceImpl);
    }
}

执行结果

10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入点this测试!

10:27:12.277 [main] INFO com.ms.aop.jthis.demo1.Client - false

修改代码

@EnableAspectJAutoProxy(proxyTargetClass = true)
proxyTargetClass=true表示强制使用cglib来生成代理对象

执行结果:

10:34:50.755 [main] INFO com.ms.aop.jthis.demo1.ServiceImpl - 切入点this测试!

10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Interceptor1 - 方法执行完毕

10:34:50.756 [main] INFO com.ms.aop.jthis.demo1.Client - true

service 为 ServiceImpl类型的对象,所以会被拦截,因为熟悉CGLIB理论知识的同学都知道,CGLIB生成的代理对象是源类型的子类,因此service肯定是ServiceImpl类型的对象了,因为多态属于关系。 

四、target表达式

目标对象为指定的类型被拦截

target(com.xyz.service.AccountService)
目标对象为AccountService类型的会被代理

this 和 target 的不同点

五、args 表达式

匹配方法中的参数

匹配只有一个参数,且类型为
com.ms.aop.args.demo1.UserModel@Pointcut("args(com.ms.aop.args.demo1.UserModel)")
- 匹配多个参数
args(type1,type2,typeN)

匹配任意多个参数

匹配第一个参数类型为com.ms.aop.args.demo1.UserModel的所有方法, .. 表示任意个参数
@Pointcut("args(com.ms.aop.args.demo1.UserModel,..)")

六、@target表达式

匹配的目标对象的类有一个指定的注解

目标对象中包含com.ms.aop.jtarget.Annotation1注解,调用该目标对象的任意方法都会被拦截
@target(com.ms.aop.jtarget.Annotation1)

七、@within表达式

指定匹配必须包含某个注解的类里的所有连接点

声明有com.ms.aop.jwithin.Annotation1注解的类中的所有方法都会被拦截
​​​​​​​@within(com.ms.aop.jwithin.Annotation1)

@target 和 @within 的不同点

八、@annotation表达式

匹配有指定注解的方法(注解作用在方法上面)

@annotation(com.ms.aop.jannotation.demo2.Annotation1)

被调用的方法包含指定的注解

九、@args表达式

方法参数所属的类型上有指定的注解,被匹配

注意:是方法参数所属的类型上有指定的注解,不是方法参数中有注解

匹配1个参数,且第1个参数所属的类中有Anno1注解

切点表达式组合

另外,可以使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系。

@Pointcut("@target(org.springframework.stereotype.Repository)")
public void repositoryMethods() {}

@Pointcut("execution(* *..create*(Long,..))")
public void firstLongParamMethods() {}

@Pointcut("repositoryMethods() && firstLongParamMethods()")
public void entityCreationMethods() {}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文