一、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. 安装Linux的步骤 包含linux下安装jdk,及mysql

    https://mirrors.tuna.tsinghua.edu.cn/centos/7.9.2009/isos/x86_64/ 镜像下载网址,4G 左右. 安装VMware 15版本 一路下一步, ...

  2. Java 执行控制流程

    1.带标签的break会中断并跳出标签所指的循环: 2.带标签的continue会中断本次循环,并开始标签所指处循环的下一轮循环.

  3. Linux引导过程和服务过程

    目录 一.Linux操作系统引导过程 1.1.开机自检 1.2.MBR引导 1.3.GRUB菜单 1.4.加载Linux内核 1.5.init进程初始化 二.系统初始化进程 2.1.init进程 2. ...

  4. 【笔记】偏差方差权衡 Bias Variance Trade off

    偏差方差权衡 Bias Variance Trade off 什么叫偏差,什么叫方差 根据下图来说 偏差可以看作为左下角的图片,意思就是目标为红点,但是没有一个命中,所有的点都偏离了 方差可以看作为右 ...

  5. NOIP 模拟 $26\; \rm 幻魔皇$

    题解 \(by\;zj\varphi\) 观察可发现一个点向它的子树走能到的白点,黑点数是一个斐波那契数列. 对于白色点对,可以分成两种情况: 两个白点的 \(lca\) 是其中一个白点 两个白点的 ...

  6. NOIP 模拟 $16\; \rm Star Way To Heaven$

    题解 \(by\;zj\varphi\) 看懂题!!! 从最左穿到最右,一定会经过两个星星之间或星星和边界之间,那么我们穿过时当前最优一定是走中点 而我们要求最小的距离最大,那么我们将所有星星和边界( ...

  7. TaskAwaiter<TResult> 结构

    参考网址:https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.compilerservices.taskawaiter-1?view= ...

  8. .net 的析构函数和dispose模式

  9. 【nodejs】request 和 response 对象

    request 和 response 对象的具体介绍: Request 对象 - request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性.常见属性有: req ...

  10. 对于Oracle、mysql和sql server中的部分不同理解

    1.在mysql中事务默认是自动提交的,只有设置autocommit为0的时候,才用自己commit:(提到commit不要忘了rollback哦,回滚)2.但是在oracle中必须自己commit: ...