前言
对有参注解的切面编程,最关键的两点:ProceedingJoinPoint和.getAnnotation(Process.class).属性名())。
实用
该自定义注解的功能是处理数据,目前主要实现功能是对注解进行属性克隆(只能克隆第二层哦,属于浅层克隆)。
注解类:
package com.ruoyi.system.aop;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Component
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Process {
@AliasFor("processMode")
String value() default "default";
/**
* 处理模式
* copyEntity:复制并返回您标记的方法的第一个形式参数
*/
@AliasFor("value")
String processMode() default "default";
}
切面类
package com.ruoyi.system.aop.aspect;
import com.ruoyi.system.aop.Process;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.util.Arrays;
@Aspect
@Component
@Slf4j
public class ProcessAspect {
@Pointcut("@annotation(com.ruoyi.system.aop.Process)")
public void processPointCut() {
}
@Around("processPointCut()")
public Object around(ProceedingJoinPoint joinPoint) {
//around后面千万不要throw ,因为父类方法没有throw任何东西
//如果强行throw,编译时不会报错,但是运行时报错UndeclaredThrowableException
System.err.println("around processpoint");
System.out.println(joinPoint.getSignature().getName());
switch (((MethodSignature) (joinPoint//切点
.getSignature()))
/*
* 获取签名,因为注解写在方法上,所以获取的签名是方法签名
* 该方法返回一个Signature对象,需要转化成MethodSignature对象
* 否则链式编程.getMethod()无法被使用
*/
.getMethod()//获取注解标记的方法
.getAnnotation(Process.class).processMode()) {//获取方法上标记的注解,获取注解当中当前所存储的属性值
case "copyEntity":
return this.copy(joinPoint.getArgs()[0]);
default: {
try {
new Exception().printStackTrace(new PrintStream(Arrays.toString(new Exception().getStackTrace())
+ "\n"
+ "you haven't declared a string for the model \"processMode\" or \"value\",or the declaration values \"default\""));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
}
private Object copy(Object object) {
Object objectTarget = null;
try {
objectTarget = object.getClass().getConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
Field[] fields = object.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
fields[i].setAccessible(true);
fields[i].set(objectTarget, fields[i].get(object));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return objectTarget;
}
}
使用时:
@Process(processMode = "copyEntity")
//只有这条有用,它的目的就是为了写一个注解,并且给这个注解中的一个属性赋值
public Object copyEntity(Object object) {
return null;
}