目录

一、利用注解实现AOP的基本流程

  1.1、创建一个注解,用来注解切点(pointcut)

  1.2、创建一个service,使用上面定义的注解来指定切点

  1.3、创建Aspect,增加业务逻辑

  1.4、创建Spring配置类

  1.5、测试

二、获取自定义注解的参数

  2.1、创建带属性的自定义注解

  2.2、创建service使用带属性的自定义注解

  2.3、创建Aspect的错误示例

  2.4、创建Aspect的正确做法

  2.5、测试

三、总结

一、利用注解实现AOP的基本流程

  如果特别熟悉自定义注解实现AOP,可以直接转到第二部分:跳转

  Spring中,可以通过自定义注解的方式来实现AOP,比较简单,流程如下:  

  1.1、创建一个注解,用来注解切点(pointcut)

1
2
3
4
5
6
7
8
9
10
11
12
package cn.ganlixin.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DemoAnnotation {
    //注意这里没有定义属性
}

  

  1.2、创建一个service,使用上面定义的注解来指定切点

  这里为了节约篇幅,就不创建service接口,再创建serviceImpl来实现接口了,直接写在service中:

1
2
3
4
5
6
7
8
9
10
11
12
13
package cn.ganlixin.service;
 
import cn.ganlixin.annotation.DemoAnnotation;
import org.springframework.stereotype.Service;
 
@Service
public class DemoService {
 
    @DemoAnnotation  // 使用自定义的注解,声明该方法为切点方法
    public void demo() {
        System.out.println("this is DemoService.demo()");
    }
}

  

  1.3、创建Aspect,增加业务逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.ganlixin.aspect;
 
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
 
@Component
@Aspect
public class DemoAspect {
 
    @Before("@annotation(cn.ganlixin.annotation.DemoAnnotation)")
    public void demoBefore() {
        System.out.println("this is before output message");
    }
}

  

  1.4、创建Spring配置类

  主要做的是:指定包扫描路径

1
2
3
4
5
6
7
8
9
10
11
12
package cn.ganlixin;
 
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
 
@Configuration
@ComponentScan("cn.ganlixin")
@EnableAspectJAutoProxy
public class AppConfig {
     
}

  

  1.5、测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package cn.ganlixin;
 
import cn.ganlixin.service.DemoService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
public class AppTest {
 
    @Test
    public void testAOP1() {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
 
        DemoService demoService = context.getBean(DemoService.class);
        demoService.demo();
    }
}

  输出:

1
2
this is before output message
this is DemoService.demo()

  

二、获取自定义注解的参数

  2.1、创建带属性的自定义注解

  要获取自定义注解参数,就需要在自定义注解中增加几个属性,下面自定义的TestAnnotation中有两个属性:value和description。

1
2
3
4
5
6
7
8
9
10
11
12
13
package cn.ganlixin.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestAnnotation {
    String value();
    String description() default "default description";
}

  

  2.2、创建service使用带属性的自定义注解

  service中有两个方法,分别使用了自定义注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package cn.ganlixin.service;
 
import cn.ganlixin.annotation.TestAnnotation;
import org.springframework.stereotype.Service;
 
@Service
public class TestService {
     
    @TestAnnotation("this is value")
    public void test1() {
        System.out.println("this is TestService.test1()");
    }
     
    @TestAnnotation(value = "this is another value", description = "this is description")
    public void test2() {
        System.out.println("this is TestService.test2()");
    }
}

  

  2.3、创建Aspect的错误示例

  在写博客之前,我也搜过相关的博客,但是发现很多博客中写的都是利用@Around来实现获取注解信息,但是我如果需要在@Before中,@After中获取又怎么办呢?虽然可以通过以下骚操作,通过@Around来模拟@Before和@After,但是还是感觉不好。

  下面还是使用@Before来实现的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package cn.ganlixin.aspect;
 
import cn.ganlixin.annotation.TestAnnotation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
 
@Component
@Aspect
public class TestAspect {
 
    @Before("@annotation(cn.ganlixin.annotation.TestAnnotation)")
    public void one(TestAnnotation testAnonotation) {
        System.out.println(testAnonotation.value());
        System.out.println(testAnonotation.description());
    }
}

  上面的代码看似没有问题,one()方法中接收一个TestAnnotation的参数,以为能够获取到切点方法的注解信息,但是,IDE会告诉你如下错误:

  

  2.4、创建Aspect的正确做法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package cn.ganlixin.aspect;
 
import cn.ganlixin.annotation.TestAnnotation;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
 
@Component
@Aspect
public class TestAspect {
 
    // 先创建一个方法,方法名随意,但是需要制定@annotation为刚刚自定义的注解
    @Pointcut("@annotation(cn.ganlixin.annotation.TestAnnotation)")
    public void test() {}
 
    // 使用@Before,需要先引入上面@Pointcut注解的方法名,在加上@annotation,
    // @annotation中的值,需要和action方法中的参数名称相同(必须相同,但是名称任意)
    @Before("test() && @annotation(testAnnotation)")
    public void action(TestAnnotation testAnnotation) {
        System.out.println("Annotation value : " + testAnnotation.value());
        System.out.println("Annotation description : " + testAnnotation.description());
        System.out.println("this is TestAspect.action()");
    }
}

  划重点:

1
2
3
4
5
6
7
// 第2个示例,强调@annotation中的值,需要和方法参数名相同
@Before("test() && @annotation(abcdef)")
public void action2(TestAnnotation abcdef) {
    System.out.println("Annotation value : " + abcdef.value());
    System.out.println("Annotation description : " + abcdef.description());
    System.out.println("this is TestAspect.action()");
}

  

  2.5、测试

  Spring的配置类不用更改,测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package cn.ganlixin;
 
import cn.ganlixin.service.TestService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
public class AppTest {
    @Test
    public void testAOP2() {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        TestService testService = context.getBean(TestService.class);
         
        testService.test1();
        System.out.println("----------------------------");
        testService.test2();
    }
}

  输出:

1
2
3
4
5
6
7
8
9
Annotation value : this is value
Annotation description : default description
this is TestAspect.action()
this is TestService.test1()
----------------------------
Annotation value : this is another value
Annotation description : this is description
this is TestAspect.action()
this is TestService.test2()

  

三、总结

  要想是获取AOP中自定义注解的参数值,主要就一点:

  

如需转载,请注明文章出处,谢谢!!!
 
分类: Spring

AOP中获取自定义注解的参数值的更多相关文章

  1. [asp.net mvc 奇淫巧技] 01 - 封装上下文 - 在View中获取自定义的上下文

    我们在asp.net 开发中已经封装了最强大的HttpContext,我们可以在HttpContext中可以获取到几乎任何想获取的东西,也可以在HttpContext写入需要返回客户端的信息.但是这些 ...

  2. java反射机制获取自定义注解值和方法

    由于工作需求要应用到java反射机制,就做了一下功能demo想到这些就做了一下记录 这个demo目的是实现动态获取到定时器的方法好注解名称,废话不多说了直接上源码 1.首先需要自定义注解类 /** * ...

  3. 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  4. Spring Boot 中使用自定义注解,AOP 切面打印出入参日志及Dubbo链路追踪透传traceId

    一.使用背景 开发排查系统问题用得最多的手段就是查看系统日志,在分布式环境中一般使用 ELK 来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,由于大量的其他用户/其他线程的日志也一起输出穿 ...

  5. 使用AOP获取自定义注解的内容

    目录结构: 一:自定义注解 package org.example.annotation; import java.lang.annotation.ElementType; import java.l ...

  6. AOP通过反射获取自定义注解

    自定义注解: @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component publ ...

  7. java之aop使用及自定义注解

    目的: 1.Java注解简介 2.Java元注解(重点) 3.自定义注解 案例一(获取类与方法上的注解值) 案例二(获取类属性上的注解属性值) 案例三(获取参数修饰注解对应的属性值) 4.Aop自定义 ...

  8. 在springMVC中使用自定义注解来进行登录拦截控制

    1:java注解使用是相当频繁,特别是在搭建一些框架时,用到类的反射获取方法和属性,用的尤其多. java中元注解有四个: @Retention     @Target     @Document  ...

  9. Spring启动时获取自定义注解的属性值

    1.自定义注解 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documen ...

随机推荐

  1. 【已解决】git怎么合并多个分支到主干master

    git支持很多种工作流程,我们采用的一般是这样,远程创建一个主分支,本地每人创建功能分支,日常工作流程如下: 去自己的工作分支$ git checkout workbranch 工作.... 提交工作 ...

  2. flask uwsgi和nginx配置信息

    1. 安装 pip3 install uwsgi 2. uwsgi配置信息 创建一个uwsgi.ini文件 [uwsgi] socket=/opt/script/uwsgi.sock #启动程序时所使 ...

  3. log4j每天生成一个文件配置

    log4j.rootLogger=INFO,CONSOLE,logDailyFile log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppenderlo ...

  4. Linux Kernel PANIC(三)--Soft Panic/Oops调试及实例分析【转】

    转自:https://blog.csdn.net/gatieme/article/details/73715860 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

  5. Missing write access to /usr/local/lib/node_modules npm ERR! path /usr/local/lib/node_modules

    今天用npm下载yarn,出现Missing write access to /usr/local/lib/node_modules npm ERR! path /usr/local/lib/node ...

  6. GCC 预处理,汇编,编译,链接,连接静态库,动态库

    gcc Record gcc -E file1.c > output gcc -E file1.c -o file1.i gcc -S file1.i -o file1.s gcc -S fil ...

  7. socket服务

    1.socket_server import socket import threading server = socket.socket(socket.AF_INET, socket.SOCK_ST ...

  8. 【Spring AOP】切入点表达式(四)

    一.切入点指示符 切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下: execution:用于匹配方 ...

  9. VIJOS-P1201 高低位交换

    洛谷 P1100 高低位交换 https://www.luogu.org/problemnew/show/P1100 JDOJ 1349: VIJOS-P1201 高低位交换 https://neoo ...

  10. LG5200 「USACO2019JAN」Sleepy Cow Sorting 树状数组

    \(\mathrm{Sleepy Cow Sorting}\) 问题描述 LG5200 题解 树状数组. 设\(c[i]\)代表\([1,i]\)中归位数. 显然最终的目的是将整个序列排序为一个上升序 ...