在之前的文章中我已经详细的说明了关于Spring的aop的使用,大家有兴趣的可以翻一下之前的文章【spring】Spring的aop的使用详解
今天,我就带着大家一起来走进aop源码,看看其内部具体是如何实现的。
一、环境准备
1.1、引入依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.1.6.RELEASE</spring.version>
<junit.version>4.12</junit.version>
<slf4j.version>1.7.35</slf4j.version>
<aspectjweaver.version>1.8.9</aspectjweaver.version>
<json.version>1.2.27</json.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${json.version}</version>
</dependency>
</dependencies>
1.2、编写接口和实现类
package com.sxx.controller.service;
public interface UserService {
void work();
}
package com.sxx.controller.service.impl;
import com.sxx.controller.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public void work() {
System.out.println("UserServiceImpl执行了");
}
}
1.3、编写切面
package com.sxx.controller.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
@Aspect
public class UserServiceAspect {
@Pointcut(value = "execution(* com.sxx.controller.service.impl.*.* (..))")
public void pointCut() {
System.out.println("@进入切点...");
}
//环绕通知(连接到切入点开始执行,下一步进入前置通知,在下一步才是执行操作方法)
@Around(value = "pointCut()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("@Around进入环绕通知...");
long startTime = System.currentTimeMillis();
// 调用了下一个拦截器,递归调用ReflectiveMethodInvocation#proceed
joinPoint.proceed(); // ===> debug into,环绕round的下一个链
long endTime = System.currentTimeMillis();
System.out.printf("@Around方法执行耗时>>>>>: %s%n", endTime - startTime);
}
//前置通知(进入环绕后执行,下一步执行方法)
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println("@Before进入前置通知:" + Arrays.toString(joinPoint.getArgs()));
}
//异常通知(出错时执行)
@AfterThrowing(value = "pointCut()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
System.out.println("@AfterThrowing进入异常通知" + Arrays.toString(joinPoint.getArgs()));
}
//后置通知(返回之前执行)
@After(value = "pointCut()")
public void after() {
System.out.println("@After进入后置通知...");
}
//最终通知(正常返回通知,最后执行,出现异常)
@AfterReturning(value = "pointCut()")
public void afterReturning() {
System.out.println("@AfterReturning进入最终通知...End!");
}
}
1.4、编写xml文件
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.or