我们有一个非常复杂的注释结构,可以放在一个字段上。这个结构放在很多字段上,只有1个参数在改变。其余的只是复制粘贴代码。这种方法有效,但有点难看:
@Type(type = "com.company.ConstantClass", parameters = @Parameter(name = "parameterClass", value = "com.company.ChangingClass"))
ChangingClass parameter;
在上面的示例中,只有参数value
会发生变化,其余的只是复制粘贴。
我想做的是创建一个"快捷方式"仅包含value
参数的注释。在我们处理此问题时,参数可以从String
更改为Class
,以使代码不易受到重构错误的影响。
例如:
@Shortcut(value = ChangingClass.class)
ChangingClass parameter;
一个问题是@Type
注释只能放在字段或方法上,所以我不能简单地创建一个带注释的注释"。
答案 0 :(得分:0)
你问的是不可行的。 你可以做的是指定默认值。
public @interface Type
{
String type() default "com.company.ConstantClass";
Parameter parameter();
}
public @interface Parameter
{
String name() default "parameterClass";
String value();
}
我认为结果很干净。
@Type(parameter = @Parameter("com.company.ChangingClass"))
private ChangingClass parameter;
OR ,您必须重构提取注释值的代码以使用默认值。这样,您只能使用单个属性进行注释。
答案 1 :(得分:0)
如果第三方库使用注释,则必须加载类对象。所以我猜有一个像
这样的APIpublic void load(Class<?> clz);
您可以在加载课程之前定义@Shortcut
并处理它。您可以使用我的实用程序类AnnotationUtil
在运行时添加/删除/更改注释:
public static void processShortcut(Field f) {
Shortcut s = f.getAnnotation(Shortcut.class);
if (s != null) {
AnnotationUtil.removeAnnotation(f, Shortcut.class); // remove @Shortcut
Parameter p = AnnotationUtil.createAnnotationFromMap(Parameter.class, ImmutableMap.of("name", "parameterClass", "value", s.value().getName())); // create @Parameter
Type t = AnnotationUtil.createAnnotationFromMap(Type.class,
ImmutableMap.of("type", "com.company.ConstantClass", "parameters", new Parameter[] { p })); // create @Type
AnnotationUtil.addAnnotation(f, t); // add it on field
}
}
让我们测试一下我们的代码
public static class User {
@Shortcut(User.class)
public Object parameter;
}
public static void main(String[] args) {
Class<?> clz = User.class;
// process shortcut on all fields
Arrays.stream(clz.getFields()).map(ReflectUtil::getRootField).forEach(f -> processShortcut(f));
// submit to 3rd-party lib
thirdParty(clz);
}
public static void thirdParty(Class<?> clz) {
// this mock your 3rd party entry
Arrays.stream(clz.getFields()).forEach(f -> System.out.println(f + "\t" + f.getAnnotation(Type.class)));
}
输出
public java.lang.Object xdean.stackoverflow.java.annotation.Q48386072$User.parameter @xdean.stackoverflow.java.annotation.Q48386072$Type(type=com.company.ConstantClass, parameters=[@xdean.stackoverflow.java.annotation.Q48386072$Parameter(name=parameterClass, value=xdean.stackoverflow.java.annotation.Q48386072$User)])
您可以看到@Type
确实添加到该字段。
您可以在github上找到完整的代码。