1. 创建注解类
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface DoSomeThing {
String key() default "";
String cacheName();
boolean flag() default false;
}
package com.example.demo.annotation;
import com.example.demo.enums.TypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface LogAnno {
String name();
Class clazz();
TypeEnum type() default TypeEnum.NATIVE;
}
2. 创建解析器ElParser
package com.example.demo.aspect;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class ElParser {
private static ExpressionParser parser = new SpelExpressionParser();
public static String getKey(String key, String[] paramNames, Object[] args) {
Expression expression = parser.parseExpression(key);
EvaluationContext context = new StandardEvaluationContext();
if (args.length <= 0) {
return null;
}
for (int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
return expression.getValue(context, String.class);
}
public static <T> T getValue(String key, String[] paramNames, Object[] args, Class<T> clz) {
Expression expression = parser.parseExpression(key);
EvaluationContext context = new StandardEvaluationContext();
if (args.length <= 0) {
return null;
}
for (int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
return expression.getValue(context, clz);
}
public static void main(String[] args) {
stringMethod();
}
private static void stringMethod() {
String key = "#l+'='+#j";
String k1 = "l";
String k2 = "j";
String[] keyNames = new String[]{k1, k2};
Object[] arg = new Object[]{"fisher", "18"};
System.out.println(ElParser.getKey(key, keyNames, arg));
}
}

3. 创建切面类
- 获取字符串类型入参的切面AspectAnnotation
package com.example.demo.aspect;
import com.example.demo.annotation.DoSomeThing;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
@Component
@Aspect
@Slf4j
public class AspectAnnotation {
@Around(value = "@annotation(doSomeThing)")
public Object around(ProceedingJoinPoint point, DoSomeThing doSomeThing) throws Throwable {
String className = point.getSourceLocation().getWithinType().getName();
Signature signature = point.getSignature();
String methodName = signature.getName();
String key = null;
if (StringUtils.hasText(doSomeThing.key())) {
key = getKey(doSomeThing.key(), point);
}
String cacheName = doSomeThing.cacheName();
boolean flag = doSomeThing.flag();
System.out.println("==============around前置通知=========");
Object result = null;
try {
result = point.proceed();
} catch (Exception e) {
log.error(String.format("%s %s %s", className, methodName, e.getMessage()));
}
if (flag) {
log.info(String.format("%s %s", cacheName, key));
}
Object[] args = point.getArgs();
System.out.println("==============around后置通知=========" + Arrays.asList(args).toString());
return result;
}
private String getKey(String key, ProceedingJoinPoint point) {
Method method = ((MethodSignature) point.getSignature()).getMethod();
Parameter[] parameters = method.getParameters();
String[] paramNames = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
paramNames[i] = parameters[i].getName();
}
return ElParser.getKey(key, paramNames, point.getArgs());
}
}
package com.example.demo.aspect;
import com.example.demo.annotation.LogAnno;
import com.example.demo.entity.User;
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.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
@Component
@Aspect
@Slf4j
public class LogAspect {
@Around(value = "@annotation(logAnno)")
public Object around(ProceedingJoinPoint point, LogAnno logAnno) throws Throwable {
String className = point.getTarget().getClass().getName();
Method method = ((MethodSignature) point.getSignature()).getMethod();
String methodName = method.getName();
String title = "[" + className + "][" + methodName + "]" + logAnno.type().getMethod();
String feedBack = "feedBack";
Object key = getKey(logAnno.name(), point, logAnno.clazz());
log.info(title + " = {}", getDTO(key));
Object result = null;
try {
result = point.proceed();
log.info(title + " " + feedBack + " = {}", getDTO(result));
} catch (Exception e) {
log.error(title, e);
}
return result;
}
private Object getDTO(Object key) {
if (key instanceof User) {
log.info("this is user class");
}
return key;
}
private <T> T getKey(String key, ProceedingJoinPoint point, Class<T> clazz) {
Method method = ((MethodSignature) point.getSignature()).getMethod();
Parameter[] parameters = method.getParameters();
String[] paramNames = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
paramNames[i] = parameters[i].getName();
}
return ElParser.getValue(key, paramNames, point.getArgs(), clazz);
}
}
4. 创建实体类User
package com.example.demo.entity;
import lombok.Data;
@Data
public class User {
private String name;
private Integer age;
}
5. 创建枚举类TypeEnum
package com.example.demo.enums;
public enum TypeEnum {
NATIVE("native method"),
THIRD("third method");
private String method;
TypeEnum(String method) {
this.method = method;
}
public String getMethod() {
return method;
}
}
6. 创建service
- 使用#name+’;’+#user获取字符串name和对象user的值,用
;
号分割,并开启日志记录
package com.example.demo.service;
import com.example.demo.annotation.DoSomeThing;
import com.example.demo.annotation.LogAnno;
import com.example.demo.entity.User;
import com.example.demo.enums.TypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class UserService {
@DoSomeThing(key = "#name+';'+#user", cacheName = "MethodName", flag = true)
public User getUserByName(String name, User user) {
log.info(String.format("%s;%s", name, user));
return user;
}
@LogAnno(name = "#user", clazz = User.class, type = TypeEnum.NATIVE)
public User getUserClass(User user) {
log.info(user.toString());
return user;
}
}
7. 创建controller
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class UserController {
@Resource
UserService userService;
@GetMapping("/test1")
public User test1() {
User user = new User();
user.setName("fisher");
user.setAge(18);
return userService.getUserByName("fisher", user);
}
@GetMapping("/test2")
public User test2() {
User user = new User();
user.setName("fisher");
user.setAge(18);
return userService.getUserClass(user);
}
}
8. 测试获取方法入参

- 在切面类AspectAnnotation中,成功打印方法的入参

