add AnnotationProxy

This commit is contained in:
Looly 2022-03-03 23:54:47 +08:00
parent bfac3a54df
commit ccc9f2568f
4 changed files with 104 additions and 17 deletions

View File

@ -6,6 +6,7 @@
### 🐣新特性
* 【http 】 HttpRequest.form采用TableMap方式issue#I4W427@gitee
* 【core 】 AnnotationUtil增加getAnnotationAlias方法pr#554@gitee
### 🐞Bug修复
* 【core 】 修复ObjectUtil.hasNull传入null返回true的问题pr#555@gitee

View File

@ -0,0 +1,88 @@
package cn.hutool.core.annotation;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 注解代理<br>
* 通过代理指定注解可以自定义调用注解的方法逻辑如支持{@link Alias} 注解
*
* @param <T> 注解类型
* @since 5.7.23
*/
public class AnnotationProxy<T extends Annotation> implements Annotation, InvocationHandler, Serializable {
private static final long serialVersionUID = 1L;
private final T annotation;
private final Class<T> type;
private final Map<String, Object> attributes;
/**
* 构造
*
* @param annotation 注解
*/
public AnnotationProxy(T annotation) {
this.annotation = annotation;
//noinspection unchecked
this.type = (Class<T>) annotation.annotationType();
this.attributes = initAttributes();
}
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 注解别名
Alias alias = method.getAnnotation(Alias.class);
if(null != alias){
final String name = alias.value();
if(StrUtil.isNotBlank(name)){
if(false == attributes.containsKey(name)){
throw new IllegalArgumentException(StrUtil.format("No method for alias: [{}]", name));
}
return attributes.get(name);
}
}
final Object value = attributes.get(method.getName());
if (value != null) {
return value;
}
return method.invoke(this, args);
}
/**
* 初始化注解的属性<br>
* 此方法预先调用所有注解的方法将注解方法值缓存于attributes中
*
* @return 属性方法结果映射
*/
private Map<String, Object> initAttributes() {
final Method[] methods = ReflectUtil.getMethods(this.type);
final Map<String, Object> attributes = new HashMap<>(methods.length, 1);
for (Method method : methods) {
// 跳过匿名内部类自动生成的方法
if (method.isSynthetic()) {
continue;
}
attributes.put(method.getName(), ReflectUtil.invoke(this.annotation, method));
}
return attributes;
}
}

View File

@ -2,11 +2,15 @@ package cn.hutool.core.annotation;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import java.lang.annotation.*;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@ -38,7 +42,7 @@ public class AnnotationUtil {
/**
* 获取指定注解
*
* @param annotationEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param annotationEle {@link AnnotatedElement}可以是ClassMethodFieldConstructorReflectPermission
* @param isToCombination 是否为转换为组合注解
* @return 注解对象
*/
@ -201,9 +205,9 @@ public class AnnotationUtil {
/**
* 设置新的注解的属性字段
*
* @param annotation 注解对象
* @param annotation 注解对象
* @param annotationField 注解属性字段名称
* @param value 要更新的属性值
* @param value 要更新的属性值
* @since 5.5.2
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@ -219,18 +223,11 @@ public class AnnotationUtil {
* @param annotationType 注解类型Class
* @param <T> 注解类型
* @return 别名支持后的注解
* @since 5.7.23
*/
@SuppressWarnings("unchecked")
public static <T extends Annotation> T getAnnotationAlias(AnnotatedElement annotationEle, Class<T> annotationType) {
T annotation = getAnnotation(annotationEle, annotationType);
Object o = Proxy.newProxyInstance(annotationType.getClassLoader(), new Class[]{annotationType}, (proxy, method, args) -> {
Alias alias = method.getAnnotation(Alias.class);
if (ObjectUtil.isNotNull(alias) && StrUtil.isNotBlank(alias.value())) {
Method aliasMethod = annotationType.getMethod(alias.value());
return ReflectUtil.invoke(annotation, aliasMethod);
}
return method.invoke(args);
});
return (T) o;
final T annotation = getAnnotation(annotationEle, annotationType);
return (T) Proxy.newProxyInstance(annotationType.getClassLoader(), new Class[]{annotationType}, new AnnotationProxy<>(annotation));
}
}

View File

@ -386,7 +386,8 @@ public class ReflectUtil {
}
/**
* 获得指定类过滤后的Public方法列表
* 获得指定类过滤后的Public方法列表<br>
* TODO 6.x此方法更改返回Method[]
*
* @param clazz 查找方法的类
* @param filter 过滤器