[英]How to implement with AutoBean a list of different base types like String, Integer, etc.?
[英]How to implement annotations to limit number of member functions, function types, etc. like FunctionalInterface?
有许多内部Java注释,例如SuppressWarning
, FunctionalInterface
等,它们可以使用该注释限制类的成员,扩展类甚至指定编译器选项,但是普通程序员如何才能构成此类注释?
我搜索的注释主题和所有我能找到的是增加了一些元值注释像这样 ,以及如何使用注释,但没有什么我能找到解释如何实现先进的注解。 任何方向都会有所帮助。
您正在寻找的是编译时注释 。
基本上,注释处理可以基于其RetentionPolicy
。 根据Java文档 , RetentionPolicy
有3种类型-
CLASS批注由编译器记录在类文件中,但在运行时无需由VM保留。
RUNTIME批注将由编译器记录在类文件中,并在运行时由VM保留,因此可以通过反射方式读取它们。
源注释将由编译器丢弃。
编译时注释处理与RetentionPolicy.SOURCE
有关,因为您希望在编译时对源文件进行处理,类似于@Override
等其他注释。
以下是一个简单的编译时注释处理器的示例-
创建Maven项目-Annotation_Compile_Time-
(A)在此项目中创建一个编译时注释MyAnnotation
package xxx; 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; @Documented @Target(ElementType.TYPE) @Inherited @Retention(RetentionPolicy.SOURCE) public @interface MyAnnotation { }
(B)创建一个注释处理器MyAnnotationProcessor-
package xxx; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; @SupportedAnnotationTypes("xxx.MyAnnotation ") @SupportedSourceVersion(SourceVersion.RELEASE_8) public class MyAnnotationProcessor extends AbstractProcessor { public MyAnnotationProcessor () { super(); } @Override public boolean process(Set<? extends TypeElement> typeElementSet, RoundEnvironment roundEnv) { for (Element e : roundEnv.getRootElements()) { String className = e.toString(); String message = "Annotated class - " + className; System.out.println(message); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message); } return false; } }
(C)在目录src/main/resources/META-INF/services
具有以下内容的javax.annotation.processing.Processor
文件 -
xxx.MyAnnotationProcessor
(D)使用构建配置更新pom.xml
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <verbose>true</verbose> <fork>true</fork> <compilerArgument>-proc:none</compilerArgument> </configuration> </plugin> </plugins> </build>
(E)使用mvn clean install
编译并安装该项目。
创建另一个Maven项目-Annotation_User-该项目将使用上述项目中定义的注释。 在该项目中创建2个带有此批注的源文件
(A)AnnotationUser1-
package xxx.consumer; import xxx.MyAnnotation; @MyAnnotation public class AnnotationUser1 { private String message; public AnnotationUser1(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
(B)AnnotationUser2-
package xxx.consumer; import xxx.MyAnnotation; @MyAnnotation public class AnnotationUser2 { private String message; public AnnotationUser1(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
(C)使用注释项目依赖项更新pom.xml
<dependency> <groupId>xxx</groupId> <artifactId>Annotation_Compile_Time</artifactId> <version>1.0</version> </dependency>
现在,无论何时,只要使用mvn clean compile
编译该项目,项目1中定义的注释处理器都将被调用。 当前,处理器只是打印带有该注释的类的名称。
您也可以参考此页面了解详细信息。
下一步是分析源文件并计算否。 方法。 由于这是编译时处理,因此您不能使用Reflection API
来获取否。 方法。 一种解决方案是使用Eclipse AST解析源文件并计算no。 方法,或者您可以编写自己的逻辑。
龙目岛项目主要基于编译时注释处理。 如果您想做一些有用的事情,最好研究Project Lombok源代码
我认为您需要注释处理:
UPD:在某些情况下,您可以编写javaagent来代替,这至少要好得多,因为至少它具有诸如bytebuddy之类的工具(这是很棒的恕我直言)
我将分享我如何制作自定义注释来解决应用程序中的问题。
问题:
我正在使用Spring AOP在我的应用程序中进行日志记录。 对于logger.log()
AOP的人来说,它用简单的语言代替了在每个方法和类中编写logger.log()
,您可以告诉AOP在每个之后/之前/之后和之前做一些事情(在我的情况下是日志记录)方法。 现在的问题是,由于每个方法都将被记录下来,因此如何防止某个方法(例如authentication )或参数(例如password )被记录下来。
为此,我创建了一个注释SkipLogging
@Target(value = { ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface SkipLogging {
}
并且在我的AOP类中,我设定了一个条件:如果有任何东西带有此批注,则AOP不应对此进行记录 。 也许遵循(部分)代码会更有意义:
@Around("within(com.test..*)
public Object logAround(final ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// Log only if class/method is not annotated with SkipLogging
if (!(signature.getDeclaringType().isAnnotationPresent(SkipLogging.class)
|| method.isAnnotationPresent(SkipLogging.class))) {
try {
// Log before method entry
logger.info("");
Object result = joinPoint.proceed();
// Log after method exit
logger.info("");
return result;
} catch (Exception e) {
// Log after exception
logger.error("");
throw e;
}
} else {
return joinPoint.proceed();
}
}
无需赘述,请看一下条件:
if (!(signature.getDeclaringType().isAnnotationPresent(SkipLogging.class)
|| method.isAnnotationPresent(SkipLogging.class
)))
这样可以防止使用SkipLogging
注释的类和方法被记录。 同样,我编写了一些代码,用于将此批注放在参数上并跳过它们。
在接下来的步骤中,我创建了@ DebugLogging,@ ErrorLogging等批注,并在AOP中进行了检查,以便根据当前批注编写调试日志或错误日志。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.