SpringBoot AOP注解写法

1.Spring AOP五种通知详情

1)环绕通知 @Around 环绕通知围绕在连接点前后
2)前置通知 @Before 在连接点前面执行
方法进行
3)环绕通知 @Around 环绕通知围绕在连接点前后
4)后置通知 @After 在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容
5)正常返回通知 @AfterReturning 在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行

2.切入点指示符

execution 用于匹配方法执行的连接点;
within 用于匹配指定类型内的方法执行;
this 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target 用于匹配当前目标对象类型的执行方法;注意是 目标对象的类型匹配,这样就不包括引入接口也类型匹配;
args 用于匹配当前执行的方法传入的参数为指定类型的执行方法;
@within 用于匹配所以持有指定注解类型内的方法;
@target 用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@args 用于匹配当前执行的方法传入的参数持有指定注解的执行;
@annotation 用于匹配当前执行方法持有指定注解的方法;
bean Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;
reference pointcut 表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。

3.AOP切入点详解

1)execution(public * (…)) 匹配所有的public修饰符的方法
execution(
com.test.method.des….(…))
1, execution() 表达式的主体
2, 第一个“”符号 表示返回值的类型任意
3, com.test.method.des AOP所切的服务的包名,即,需要进行横切的业务类
4, 包名后面的“…” 表示当前包及子包
5, 第二个“
” 表示类名,即所有类
6, .
(…) 表示任何方法名,括号表示参数,两个点表示任何参数类型

范例

  • public * *(…) 任何公共方法的执行
  • com.learn…IHelloService.*() com.learn包及所有子包下IHelloService接口中的任何无参方法
  • com.learn….(…) com.learn包及所有子包下任何类的任何方法
  • com.learn…IHelloService.() com.learn包及所有子包下IHelloService接口的任何只有一个参数方法
  • (!com.learn…IHelloService+).*(…) 非“com.learn包及所有子包下IHelloService接口及子类型”的任何方法
  • com.learn…IHelloService+.() com.learn包及所有子包下IHelloService接口及子类型的的任何无参方法
    com.learn…IHelloService.test
    (java.util.Date) com.learn包及所有子包下IHelloService前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的,如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的;
    *com.learn…IHelloService.test(…) throws IllegalArgumentException, ArrayIndexOutOfBoundsException com.learn包及所有子包下IHelloService前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常
  • (com.learn…IHelloService+ && java.io.Serializable+).*(…) 任何实现了com.learn包及所有子包下 IHelloService接口和java.io.Serializable接口的类型的任何方法
    @java.lang.Deprecated * *(…) 任何持有@java.lang.Deprecated注解的方法
    @(java.lang.Deprecated || com.learn…Secure) * *(…) 任何持有@java.lang.Deprecated或@com.learn…Secure注解的方法
    (@com.learn…Secure *) *(…) 任何返回值类型持有@com.learn…Secure的方法
  • (@com.learn…Secure ).(…) 任何定义方法的类型持有@com.learn…Secure的方法
  • (@com.learn…Secure () , @com.learn…Secure (*)) 任何签名带有两个参数的方法,且这个两个参数都被@Secure标记了,如public void test(@Secure String str1, @Secure String str1)
  • *((@ com.learn…Secure *))或 * *(@ com.learn…Secure *) 任何带有一个参数的方法,且该参数类型持有@com.learn…Secure;如public void test(Model model);且Model类上持有@Secure注解
  • *( @com.learn…Secure (@com.learn…Secure *) , @ com.learn…Secure (@com.learn…Secure *)) 任何带有两个参数的方法,且这两个参数都被@com.learn…Secure标记了;且这两个参数的类型上都持有@ com.learn…Secure;
    *( java.util.Map<com.learn…Model, com.learn…Model> , …) 任何带有一个java.util.Map参数的方法,且该参数类型是以< com.learn…Model, com.learn…Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“ *( java.util.HashMap<com.learn…Model,com.learn…Model> , …)”进行匹配; 而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配 * *(java.util.Collection<@com.learn…Secure *>) 任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@com.learn…Secure注解; 如public void test(Collection collection);Model类型上持有@com.learn…Secure * *(java.util.Set<? extends HashMap>) 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型继承与HashMap; Spring AOP目前测试不能正常工作
  • *(java.util.List<? super HashMap>) 任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型是HashMap的基类型;如public voi test(Map map);Spring AOP目前测试不能正常工作
  • (<@com.learn…Secure *>) 任何带有一个参数的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@com.learn…Secure注解;Spring AOP目前测试不能正常工作

4.demo

  1. 依赖
  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.创建注解

//作用域 作用于方法和类上
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented //表示把注解生成在Javadoc中
@Inherited //表示可以被继承
public @interface MySecure {

    //注解的参数:类型+参数名()[default 默认值];
    String name() default "";

    String[] role() default {"user"};
}
  1. 切面
@Component
@Aspect
public class MySecureAspect {


    @Before("@annotation(MySecure)")
    public void dopointcut(JoinPoint jp){
        System.out.println("方法运行前检查");
        MethodSignature signature = (MethodSignature)jp.getSignature();
        //获取注解上的值
        String[] role = signature.getMethod().getAnnotation(MySecure.class).role();
        for (String s : role) {
            System.out.println("========获取传入注解的role值========="+s);
        }
        //获取该方法上的请求参数
        Parameter[] parameters = signature.getMethod().getParameters();
        for (Parameter s : parameters) {
            System.out.println("========获取该方法上的请求参数========="+s.toString());
        }
        //获取方法
        String method = signature.getMethod().toString();
        System.out.println("========method========="+method);

        //获取用户ip地址
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String IpAdr = request.getRemoteAddr();
        System.out.println("========获取用户ip地址========="+IpAdr);
    }

   //扫描com.example.demo.aop.service包下的所有的类的方法
    @AfterReturning("execution(* com.example.demo.aop.service..*.*(..))")
    public void log(){
        System.out.println("========方法正常执行完成======");
    }
}

4.测试 (UserServcie的包com.example.demo.aop.service)

@Service
public class UserServcie {

    @MySecure(role = {"admin"})
    public void login(String username,String password){
        System.out.println("=======这是一个登录方法========");
    }
}

打印结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值