一、AOP注解

1、介绍

  上一节介绍了 AspectJ 框架如何实现 AOP,具体的实现方式是通过 xml 来进行配置的。xml 方式思路清晰,便于理解,但是书写过于麻烦。这一节介绍注解的方式来进行 AOP 配置。

2、案例(注解)

  定义目标对象(被代理的对象)

 1 // 定义一个接口
2 public interface ITeacher {
3 void teach();
4 int add(int i, int j);
5 }
6
7 // 定义目标对象
8 @Service
9 public class Teacher implements ITeacher {
10 @Override
11 public void teach() {
12 System.out.println("老师正在上课");
13 }
14
15 @Override
16 public int add(int i, int j) {
17 int add = i + j;
18 System.out.println("执行目标方法:老师正在做加法,结果为:" + add);
19 // int throwable = 10 / 0; 测试异常通知
20 return add;
21 }
22
23 // 目标对象自己的方法,此方法不是接口所以无法代理
24 public void sayHello() {
25 System.out.println("老师会说hello");
26 }
27
28 }

  编写一个切面类(通知)

 1 // 创建切面类(包含各种通知)
2 @Component
3 @Aspect
4 public class MyAspect {
5
6 // 1.先定义切入点表达式
7 @Pointcut("execution(* com.lx.spring.day4.ITeacher.*(..))")
8 private void myPointcut() {
9
10 }
11
12 // 2.标识此方法为一个前置通知,用来切满足后面切点表达式的方法
13 @Before("myPointcut()")
14 public void myBefore(JoinPoint joinPoint) {
15 System.out.println("前置通知:方法增强myBefore()" + " , -->" + joinPoint.getSignature().getName());
16 }
17
18 @AfterReturning(value = "myPointcut()", returning = "object")
19 public void myAfterReturning(JoinPoint joinPoint, Object object) {
20 System.out.println("后置通知:方法增强myAfterReturning()" + " , -->" + joinPoint.getSignature().getName() + " , -->" + object);
21 }
22
23 public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
24 System.out.println("============环绕前==============");
25 Object obj = joinPoint.proceed(); // 手动执行目标方法
26 System.out.println("============环绕后==============");
27 return obj;
28 }
29
30 public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
31 System.out.println("抛出异常通知:" + e.getMessage());
32 }
33
34 public void myAfter() {
35 System.out.println("最终通知:方法增强myAfter()");
36 }
37
38 }

  编写配置文件 application.xml

1 <!-- 1.自动扫描(自动注入bean) -->
2 <context:component-scan base-package="com.lx.spring.day4"/>
3
4 <!-- 2.扫描 @Aspect 告诉 spring 这是一个切面类 -->
5 <aop:aspectj-autoproxy/>
 1 // 测试类
2 public class Main {
3 public static void main(String[] args) {
4 ApplicationContext app = new ClassPathXmlApplicationContext("app4.xml");
5 ITeacher iTeacher = app.getBean(ITeacher.class);
6
7 iTeacher.add(11, 24);
8 }
9 }
10
11 // 结果
12 前置通知:方法增强myBefore() , -->add
13 执行目标方法:老师正在做加法,结果为:35
14 后置通知:方法增强myAfterReturning() , -->add , -->35

  说明:对比 xml 的配置,不难理解注解的方式。

  @Service @Component
  <context:component-scan base-package="com.lx.spring.day4"/>

  用于 Spring 扫描并注册bean。

  @Aspect:指明这是一个切面类
  <aop:aspectj-autoproxy/>:开启切面注解扫描

3、优先级

  有多个增强类对同一个方法进行增强,设置增强类优先级,在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高。

1 @Component
2 @Aspect
3 @Order(1)
4 public class MyAspect2 {}

  优先级:这里的优先级,只会影响两个增强类对应的方法,执行的先后顺序。并不会只执行优先级高的。

二、AOP+自定义注解

  通过AOP+自定义注解的方式,可以实现前面说的抽取公共非业务模块,对业务逻辑的增强。比如:

  需求:①想要对业务逻辑层的所有方法,打印出入参和出参,做日志管理。②对业务逻辑层的方法入口,开启事务,逻辑执行后,提交事务,等。

  自定义注解

1 // 用于日志打印
2 @Target({ElementType.METHOD})
3 @Retention(RetentionPolicy.RUNTIME)
4 @Documented
5 public @interface Log {
6
7 String value() default "";
8 }
  编写切面类(通知)
 1 @Component
2 @Aspect
3 public class MyAspect {
4
5 // 定义切入点为 有注解Log的方法
6 @Pointcut("@annotation(com.lx.spring.day5.Log) ")
7 private void myLogPointcut() {
8
9 }
10
11 // 为切入点增强一个环绕通知,可以在这里写打印入参出参的逻辑
12 @Around("myLogPointcut()")
13 public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
14 System.out.println("============环绕前==============");
15 Object obj = joinPoint.proceed(); // 手动执行目标方法
16 System.out.println("============环绕后==============");
17 return obj;
18 }
19
20 }
  在相应的方法上加注解
 1 @Service
2 public class Teacher implements ITeacher {
3
4 // 为需要打印入参出参的方法 加上@Log注解即可
5 @Log
6 @Override
7 public int add(int i, int j) {
8 int add = i + j;
9 System.out.println("执行目标方法:老师正在做加法,结果为:" + add);
10 // int throwable = 10 / 0; 测试异常通知
11 return add;
12 }
13
14 }
  测试类
 1 public class Main {
2 public static void main(String[] args) {
3 ApplicationContext app = new ClassPathXmlApplicationContext("app4.xml");
4 ITeacher iTeacher = app.getBean(ITeacher.class);
5
6 iTeacher.add(11, 24);
7 }
8 }
9
10 // 结果
11 ============环绕前==============
12 执行目标方法:老师正在做加法,结果为:35
13 ============环绕后==============

Spring5(七)——AOP注解的更多相关文章

  1. Spring详解(七)------AOP 注解

    上一篇博客我们讲解了 AspectJ 框架如何实现 AOP,然后具体的实现方式我们是通过 xml 来进行配置的.xml 方式思路清晰,便于理解,但是书写过于麻烦.这篇博客我们将用 注解 的方式来进行 ...

  2. 来一手 AOP 注解方式进行日志记录

    系统日志对于定位/排查问题的重要性不言而喻,相信许多开发和运维都深有体会. 通过日志追踪代码运行状况,模拟系统执行情况,并迅速定位代码/部署环境问题. 系统日志同样也是数据统计/建模的重要依据,通过分 ...

  3. Spring详解(六)------AOP 注解

    上一篇博客我们讲解了 AspectJ 框架如何实现 AOP,然后具体的实现方式我们是通过 xml 来进行配置的.xml 方式思路清晰,便于理解,但是书写过于麻烦.这篇博客我们将用 注解 的方式来进行 ...

  4. SpringBoot —— AOP注解式拦截与方法规则拦截

    AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件. SpringBoot中AOP的使用 ...

  5. Spring AOP注解为什么失效?90%Java程序员不知道

    使用Spring Aop注解的时候,如@Transactional, @Cacheable等注解一般需要在类方法第一个入口的地方加,不然不会生效. 如下面几种场景 1.Controller直接调用Se ...

  6. Spring入门(三)— AOP注解、jdbc模板、事务

    一.AOP注解开发 导入jar包 aop联盟包. aspectJ实现包 . spring-aop-xxx.jar . spring-aspect-xxx.jar 导入约束 aop约束 托管扩展类和被扩 ...

  7. SpringBoot整合Mybatis多数据源 (AOP+注解)

    SpringBoot整合Mybatis多数据源 (AOP+注解) 1.pom.xml文件(开发用的JDK 10) <?xml version="1.0" encoding=& ...

  8. Spring AOP注解形式简单实现

    实现步骤: 1:导入类扫描的注解解析器 命名空间:xmlns:context="http://www.springframework.org/schema/context" xsi ...

  9. AOP注解不起作用的debug结果

    经过2天的调试,我发现AOP注解配置不起作用居然是表达式的错误导致的 在xml文件中配置的base-package有关,初步认为@PointCut只能使用base-package..*(..)这样的方 ...

随机推荐

  1. TCP可靠传输

    1. TCP 可靠性如何保证? 信道可靠:用三次握手.四次挥手保证连接正确: 数据正确:分区编号.校验和.超时重传: 传输控制:流量控制.拥塞控制 2. 重传机制 TCP可靠传输方式是序列号与确认应答 ...

  2. CodeReview of JDK Source Code

    jdk1.6.0_35/src.zip, only java package is reviewd(full package review caused a OutofMemory on java h ...

  3. MySQL-16-主从复制进阶

    延时从库 介绍 延时从库: 是我们人为配置的一种特殊从库,人为配置从库和主库延时N小时 为什么要有延时从库 数据库故障 物理损坏,普通的主从复制非常擅长解决物理损坏 逻辑损坏,普通主从复制没办法解决逻 ...

  4. CVE-2020-2555漏洞复现&&流量分析

    CVE-2020-2555漏洞复现&&流量分析 一.准备环境 windows7: weblogic 12.2.1.4.0 JDK版本为jdk-8u261 关于weblogic搭建可以看 ...

  5. 徒手打造基于Spark的数据工厂(Data Factory):从设计到实现

    在大数据处理和人工智能时代,数据工厂(Data Factory)无疑是一个非常重要的大数据处理平台.市面上也有成熟的相关产品,比如Azure Data Factory,不仅功能强大,而且依托微软的云计 ...

  6. docker安装完权限问题

    在用户权限下docker 命令需要 sudo 否则出现以下问题 通过将用户添加到docker用户组可以将sudo去掉,命令如下 sudo groupadd docker #添加docker用户组 su ...

  7. mongodb中时间跟实际时间相差8小时----时区问题

    遇到的问题 参考:mongo中时间跟实际时间相差8小时 Mongo中一个Collection有一个字段用来存放数据的插入时间,但记录的时间比实际时间晚了8小时. 查询得知存储在mongodb中的时间是 ...

  8. COM笔记-COM库函数

    COM在OLE32.DLL和 OLE32.LIB定义了一些常用的函数.在使用这些函数前要先调用CoInitialize来初始化COM库.当进程不再需要使用COM库函数时要调用CoUninitializ ...

  9. vue引入zTree入门

    参考1:https://blog.csdn.net/tg928600774/article/details/80911589 参考2:https://blog.csdn.net/ylhsuper/ar ...

  10. asp.net mvc 传值

    视图的查找 asp.net MVC 不需要用using 释放资源