@Retention(RetentionPolicy.SOURCE)//保留到源码即可
@Target(ElementType.FIELD)
public @interface Value {
String value() default "";
}
编写对应处理器
@SupportedAnnotationTypes("com.sk.annotations.Value")//支持的注解
@SupportedSourceVersion(SourceVersion.RELEASE_8)//支持的Java版本
public class ValueProcessor extends AbstractProcessor {
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
Map> map = getFieldMap(annotations, roundEnv);
createClassFiles(map);
return true;//返回是否处理完毕 若处理完毕不再需要其他注解处理器处理
}
private void createClassFiles(Map> map) {
for (TypeElement element : map.keySet()) {
createClassFile(element, map.get(element));
}
}
//生成对应的类文件 这里可以考虑使用模板引擎生成
private void createClassFile(TypeElement element, List fieldInfos) {
Messager messager = processingEnv.getMessager();
String fullName = element.getQualifiedName().toString();
int index = fullName.lastIndexOf('.');
String packageName = fullName.substring(0, index);
String name = fullName.substring(index + 1);
String className = "Bind_" + name;
try {
JavaFileObject file = processingEnv.getFiler().createSourceFile(packageName + "." + className);
Writer writer = file.openWriter();
writer.write("package " + packageName + ";n" +
"n" +
"import com.sk.interfaces.ValueSetter;n" +
"n" +
"public class " + className + " implements ValueSetter<" + name + "> {n" +
"n" +
" @Overriden" +
" public void applyObject(" + name + " target) {n");
for (FieldInfo fieldInfo : fieldInfos) {
writer.write("nntarget." + fieldInfo.getName() + "="" + fieldInfo.getValue() + "";n");
}
writer.write(" }n" +
"n" +
"}");
writer.close();
messager.printMessage(Diagnostic.Kind.NOTE, "成功生成:" + fullName);
} catch (IOException e) {
e.printStackTrace();
}
}
private Map> getFieldMap(Set extends TypeElement> annotations,
RoundEnvironment roundEnv) {
// Messager messager = processingEnv.getMessager();
Map> map = new HashMap<>();
for (TypeElement annotation : annotations) {//根据注解获取对应元素
Set extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation);
for (Element element : elements) {//处理每个注解元素
Value value = element.getAnnotation(Value.class);
TypeElement clazz = (TypeElement) element.getEnclosingElement();
String name = element.getSimpleName().toString();
if (!map.containsKey(clazz)) map.put(clazz, new ArrayList<>());
map.get(clazz).add(new FieldInfo(name, value.value()));
}
}
return map;
}
}
对应启动类
public class BindTool {
public static void bind(Object object){
Class> clazz = object.getClass();
String fullName = clazz.getName();
int index = fullName.lastIndexOf('.');
try {//根据类名找对应的绑定类进行绑定
Class bindClass = (Class) Class.forName(fullName.substring(0, index) + ".Bind_"
+ fullName.substring(index + 1));
ValueSetter valueSetter = bindClass.newInstance();
valueSetter.applyObject(object);
} catch (Exception e) {
e.printStackTrace();
}
}
}
一些工具类省略了,最后会放上测试项目地址
配置注解处理器 配置Maven不注解处理该项目防止死循环测试结果maven-compiler-plugin 3.8.0 1.8 1.8 -proc:none
这里实际是在编译时生成新的类并编译,并不是像lombok一样直接修改源文件
Dome地址:https://gitee.com/shaokang123/annotation-test



