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中,成功打印方法的入参