<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>spring.boot.aop</groupId>
<artifactId>annotation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>annotation</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
/**
* @author 81509
*/
@Target({
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
String value() default "";
}
@Target表示该注解可以应用的java元素类型
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
@Target其中参数类型是ElementType[]数组,其中ElementType是枚举类型
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
/** 应用于类、接口(包括注解类型)、枚举 */
TYPE,
/** Field declaration (includes enum constants) */
/** 应用于属性(包括枚举中的常量) */
FIELD,
/** Method declaration */
/** 应用于方法 */
METHOD,
/** Formal parameter declaration */
/**应用于方法的形参*/
PARAMETER,
/** Constructor declaration */
/**应用于构造函数*/
CONSTRUCTOR,
/** Local variable declaration */
/**应用于局部变量*/
LOCAL_VARIABLE,
/** Annotation type declaration */
/**应用于注解类型*/
ANNOTATION_TYPE,
/** Package declaration */
/**应用于包*/
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
/**1.8版本新增,应用于类型变量*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
/**1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)*/
TYPE_USE
}
@Retention 表明该注解的生命周期
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
@Retention 表明该注解的生命周期,其中RetentionPolicy 是枚举类型
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
/**编译时被丢弃,不包含在类文件中*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
/**JVM加载时被丢弃,包含在类文件中,默认值*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
/**由JVM 加载,包含在类文件中,在运行时可以被获取到*/
RUNTIME
}
@Document 表明该注解标记的元素可以被Javadoc 或类似的工具文档化
@Inherited 表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解
Controller:
/**
* @author 81509
*/
@RestController
public class AopController {
@RequestMapping("/logAop")
@LogAnnotation("logAopController")
public Object logAop() {
System.out.println("logAop controller");
return "logAop controller";
}
}
Aspect
/**
* @Aspect 作用是把当前类标识为一个切面供容器读取
* @author 81509
*/
@Component
@Aspect
public class LogAopAspect {
/**
* 创建切点
*/
@Pointcut(value = "@annotation(spring.boot.aop.annotation.annotation.LogAnnotation)")
public void logAop() {
}
/**
* 环绕增强,相当于MethodInterceptor
* @param proceedingJoinPoint
* @param logAnnotation
* @return
*/
@Around("@annotation(logAnnotation)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, LogAnnotation logAnnotation) {
System.out.println("方法环绕start.....");
//获取注解里参数logAnnotation.value()
System.out.println("aop around:" + logAnnotation.value());
try {
return proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
}
@Around("logAop()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("方法环绕start.....");
//获取注解里的值
System.out.println("aop around");
try {
return proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return null;
}
}
/**
* 标识一个前置增强方法,相当于BeforeAdvice的功能
* @param joinPoint
* @param logAnnotation
*/
@Before("@annotation(logAnnotation)")
public void deBefore(JoinPoint joinPoint, LogAnnotation logAnnotation){
//获取注解参数logAnnotation.value()
System.out.println("LogAop before:" + logAnnotation.value());
}
@Before("logAop()")
public void deBefore(JoinPoint joinPoint){
System.out.println("LogAop before:");
}
/**
* 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
*/
@After("@annotation(logAnnotation)")
public void after(JoinPoint joinPoint, LogAnnotation logAnnotation){
System.out.println("方法最后执行....."+logAnnotation.value());
}
@After("logAop()")
public void after(JoinPoint joinPoint){
System.out.println("方法最后执行.....");
}
/**
* 后置增强,相当于AfterReturningAdvice,方法退出时执行
* @param res
* @throws Throwable
*/
@AfterReturning(returning = "res", pointcut = "@annotation(logAnnotation)")
public void doAfterReturning(Object res, LogAnnotation logAnnotation) throws Throwable {
// 处理完请求,返回内容
System.out.println("方法的返回值 : " + res+"----"+logAnnotation.value());
}
@AfterReturning(returning = "res", pointcut = "logAop()")
public void doAfterReturning(Object res) throws Throwable {
// 处理完请求,返回内容
System.out.println("方法的返回值 : " + res);
}
/**
* 异常抛出增强,相当于ThrowsAdvice
* @param joinPoint
* @param exception
*/
@AfterThrowing(throwing = "exception", pointcut = "logAop()")
public void throes(JoinPoint joinPoint, Exception exception){
System.out.println("方法异常时执行.....");
}
}
请求 http://localhost:8080/logAop
返回结果
方法环绕start.....
aop around
方法环绕start.....
aop around:logAopController
LogAop before:
LogAop before:logAopController
logAop controller
方法最后执行.....logAopController
方法最后执行.....
方法的返回值 : logAop controller
方法的返回值 : logAop controller----logAopController
每一个通知方法都可以将第一个参数定义为JoinPoint类型(环绕通知需要定义第一个参数为ProceedingJoinPoint类型,它是 JoinPoint 的一个子类)。
JoinPoint接口提供了一系列有用的方法:
getArgs():获取连接点方法运行时的入参列表;
getSignature() :获取连接点的方法签名对象;
getTarget() :获取连接点所在的目标对象;
getThis() :获取代理对象本身;
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
Object proceed() throws Throwable:通过反射执行目标对象的连接点处的方法;
Object proceed(Object[] var1) throws Throwable:通过反射执行目标对象连接点处的方法,使用新的参数替换原来的参数。
项目地址:https://github.com/815090488/SpringBootAopAnnotation