springAop切入点表达式的种类和区别(Supported Pointcut Designators)

1、execution方式:
execution 表达式里面参数说明如下图:图内有【1】【2】【3】【4】位置一一对应的。

execution(public * *(..)) // public[1]、*[2]、*[3]、(..)[4]

(1)【1】位置 public 拦截方法的权限符(private、protected都可以),如果任何权限都可以,不写 * 作为通配符(应该省略【1】位置什么都不写)。
(2) 【2】位置的通配符 * 指方法返回值 例如(void、String)
(3). 【3】位置的通配符 * 指 包路径下指定的接口、包路径下的所有子类(*是以 包路径、类名或接口名、方法名组成)
(4) 【4】位置的通配符 (…) 指 方法入参请求的类型 例如(java.Lang.Integer、java.Lang.String)

execution方式的demo:
demo创建截图:
在这里插入图片描述
创建接口DaoExecution:

public interface DaoExecution {
    Integer method1(Integer i);
    String method2(String str);
}

创建DaoExecutionIndex1类,方法method1、method2

package com.it.app.aspectj.execution;

import org.springframework.stereotype.Component;

@Component(value = "daoExecutionIndex1")
public class DaoExecutionIndex1 implements DaoExecution{
    @Override
    public Integer method1(Integer i) {
        return i;
    }

    @Override
    public String method2(String str) {
        return str;
    }
}

创建扫描类 Appconfig 开启 @EnableAspectJAutoProxy 通过注解:

package com.it.app.aspectj.scan;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@ComponentScan("com.it.app.aspectj.execution")
@EnableAspectJAutoProxy
public class Appconfig {
}

创建切面和切点ExecutionAspect:

package com.it.app.aspectj.execution;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ExecutionAspect {

   @Pointcut("execution(public Integer com.it.app.aspectj.execution.DaoExecutionIndex1.method1*(java.lang.Integer,..))")
    public void interceptAspectjExecution() {
    }

    @Before("interceptAspectjExecution()")
    public void ExecutionRun(){
        System.out.println("before : execution拦截方法");
    }
}

执行method1、method2只拦截了method1:

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        DaoExecution daoExecution = (DaoExecution)context.getBean("daoExecutionIndex1");
        System.out.println(daoExecution.method1(1));
        System.out.println(daoExecution.method2("2"));
    }
}

结果截图只执行method1的方法:

before : execution拦截方法
1
2

2、within方式:
修改 ExecutionAspect 切面和切点

package com.it.app.aspectj.execution;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ExecutionAspect {
    @Pointcut("within( com.it.app.aspectj.execution..*)")
    public void interceptAspectjWithin() {
    }

    @Before("interceptAspectjWithin()")
    public void withinRun(){
        System.out.println("before : within拦截方法");
    }
}

执行结果将 method1、method2全部拦截

package com.it.app.aspectj;
import com.it.app.aspectj.execution.DaoExecution;
import com.it.app.aspectj.scan.Appconfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
        DaoExecution daoExecution = (DaoExecution)context.getBean("daoExecutionIndex1");
        System.out.println(daoExecution.method1(1));
        System.out.println(daoExecution.method2("2"));  
    }
}

执行结果

before : within拦截方法
1
before : within拦截方法
2

3、target方式与this:
this 和 target 对比分四种情况
(1)开启jdk动态代理、拦截相同接口
(2)开启jdk动态代理、拦截相同接口实现类
(3)开启CGLIB代理、拦截相同接口
(4)开启jCGLIB代理、拦截相同接口实现类
demo如下:
默认开启 jdk动态代理 、 true开启CGLIB代理,修改直接修改下面proxyTargetClass=false为true。

@ComponentScan("com.it.app.aspectj.execution")
//默认开启 jdk动态代理 、 true开启CGLIB代理
@EnableAspectJAutoProxy(proxyTargetClass=false)
public class Appconfig {
}

(ExecutionAspect)切面和切点拦截DaoExecution接口,
如果要变更this表达式为target则将this替换成target
如果要拦截DaoExecution的实现类,则替换为com.it.app.aspectj.execution.DaoExecutionIndex1

@Aspect
@Component
public class ExecutionAspect {
//将this替换成target    
//如果要拦截DaoExecution的实现类,则替换为com.it.app.aspectj.execution.DaoExecutionIndex1

@Pointcut("this(com.it.app.aspectj.execution.DaoExecution)")
    public void interceptAspectjThis() {
    }

    @Before("interceptAspectjThis()")
    public void thisRun(){
        System.out.println("before : this拦截方法");
    }
}

启动类

public class App {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);


        DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
        //生成代理类proxy与DaoExecutionIndex1不是一个对象
        System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
        System.out.println(daoExecution1.method1(1));
        System.out.println(daoExecution1.method2("2"));
    }
}

四种情况拦截数据情况:
(1) this 和 target动态代理 拦截接口:

生成代理类proxy与DaoExecutionIndex1不是一个对象:false
before : this拦截方法
1
before : this拦截方法
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:false
before : this拦截方法
1
before : this拦截方法
2

执行结果两者相同
(2) this 和 target动态代理 拦截接口实现类:

生成代理类proxy与DaoExecutionIndex1不是一个对象:false
1
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:false
before : this拦截方法
1
before : this拦截方法
2

只有target被拦截了
(3)开启CGLIB代理、拦截相同接口

生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2

this与target相同被拦截

(4)开启jCGLIB代理、拦截相同接口实现类

生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2
生成代理类proxy与DaoExecutionIndex1不是一个对象:true
before : this拦截方法
1
before : this拦截方法
2

两者都被拦截
4、args拦截方法参数(按照类型匹配):
demo:

@Aspect
@Component
public class ExecutionAspect {

    @Pointcut("args(java.lang.String)")
    public void interceptAspectjAgrs() {
    }

    @Before("interceptAspectjAgrs()")
    public void thisRun(){
        System.out.println("before : agrs拦截方法");
    }

}

执行结果:

public class App {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);


        DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
        //生成代理类proxy与DaoExecutionIndex1不是一个对象
       // System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
        System.out.println(daoExecution1.method1(1));
        System.out.println(daoExecution1.method2("2"));

    }
}
1
before : agrs拦截方法
2

只拦截了method2参数类型为String的。
4、@annotation通过注解去拦截:
自定义注解:

@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo {
}

切面和切点拦截配置:

@Aspect
@Component
public class ExecutionAspect {

//注解包路径    @Pointcut("@annotation(com.it.app.aspectj.execution.AnnotationDemo)")
    public void interceptAspectjAnnotation() {
    }

    @Before("interceptAspectjAnnotation()")
    public void thisRun(){
        System.out.println("before : Annotation拦截方法");
    }

}

在method1方法上添加注解

@Component(value = "daoExecutionIndex1")
public class DaoExecutionIndex1 implements DaoExecution{
    @Override
    @AnnotationDemo
    public Integer method1(Integer i) {
        return i;
    }

    @Override
    public String method2(String str) {
        return str;
    }
}

执行结果:

public class App {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);


        DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
        //生成代理类proxy与DaoExecutionIndex1不是一个对象
       // System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
        System.out.println(daoExecution1.method1(1));
        System.out.println(daoExecution1.method2("2"));

    }
}

只拦截在方法上添加注解的方法

before : Annotation拦截方法
1
2

5、@within和t@arget通过注解去拦截:
创建DaoExecutionIndexZ1类继承DaoExecutionIndex1,将注解@AnnotationDemo添加到DaoExecutionIndex1上。

@Component(value = "daoExecutionIndex1")
@AnnotationDemo
public class DaoExecutionIndex1 implements DaoExecution{
    @Override
    public Integer method1(Integer i) {
        return i;
    }

    @Override
    public String method2(String str) {
        return str;
    }
}
@Component
public class DaoExecutionIndexZ1 extends DaoExecutionIndex1{


    public Integer method3(Integer i) {
        return i;
    }
}

开启cglib代理

@ComponentScan("com.it.app.aspectj.execution")
//默认开启 jdk动态代理 、 true开启CGLIB代理
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class Appconfig {
}

注解替换只需要把@target替换成@within

package com.it.app.aspectj.execution;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ExecutionAspect {

  @Pointcut("@target(com.it.app.aspectj.execution.AnnotationDemo)")
    public void interceptAspectjAnnotation() {
    }

    @Before("interceptAspectjAnnotation()")
    public void thisRun(){
        System.out.println("before : Annotation拦截方法");
    }
}

执行结果:

public class App {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);


        DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
        //生成代理类proxy与DaoExecutionIndex1不是一个对象
       // System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
        System.out.println(daoExecution1.method1(1));
        System.out.println(daoExecution1.method2("2"));

        DaoExecutionIndexZ1 daoExecution3 = (DaoExecutionIndexZ1)context.getBean("daoExecutionIndexZ1");
        System.out.println(daoExecution3.method3(4));


    }
}

before : Annotation拦截方法
1
before : Annotation拦截方法
2
4

@within和@target执行结果一样,拦截类的方法(但@within可以拦截子类未重写方法,未拦截)。

6、@args作用是拦截方法参数:
自定义个user类,添加注解@AnnotationDemo

@AnnotationDemo
public class User {

    private String name;


    public String getName() {
        return name;
    }

    public User(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
}

添加方法method5的传入参数为user(添加接口方法)

@Component(value = "daoExecutionIndex1")
public class DaoExecutionIndex1 implements DaoExecution{
    @Override
    public Integer method1(Integer i) {
        return i;
    }

    @Override
    public String method2(String str) {
        return str;
    }

    public String method5(User user){
        return user.getName();
    }

}

表达式拦截

   @Pointcut("@args(com.it.app.aspectj.execution.AnnotationDemo)")
    public void interceptAspectjAnnotation() {
    }

    @Before("interceptAspectjAnnotation()")
    public void thisRun(){
        System.out.println("before : @args拦截方法");
    }
public class App {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);


        DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
        //生成代理类proxy与DaoExecutionIndex1不是一个对象
       // System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
        System.out.println(daoExecution1.method1(1));
        System.out.println(daoExecution1.method2("2"));
        User user = new User("dz");
        System.out.println(daoExecution1.method5(user));
    }
}

结果拦截成功method5

public class App {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);


        DaoExecution daoExecution1 = (DaoExecution)context.getBean("daoExecutionIndex1");
        //生成代理类proxy与DaoExecutionIndex1不是一个对象
       // System.out.println("生成代理类proxy与DaoExecutionIndex1不是一个对象:"+(daoExecution1 instanceof DaoExecutionIndex1));
        System.out.println(daoExecution1.method1(1));
        System.out.println(daoExecution1.method2("2"));
        User user = new User("dz");
        System.out.println(daoExecution1.method5(user));

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值