自定义注释作为方法记录的拦截器

Java大师,

我是一个很新的annotations ,并没有搜索过这么多,所以请忍受我…

我想实现一个Custom Annotation ,它将intercept一个方法调用; 从非常基本的东西开始,它可以只打印方法名称和参数,以便我可以避免使用logger语句。

像这样的示例调用:

 public MyAppObject findMyAppObjectById(Long id) throws MyCustomException { log.debug("in findMyAppObjectById(" + id + ")"); //.... } 

可以转换成:

 @LogMethodCall(Logger.DEBUG) public MyAppObject findMyAppObjectById(Long id) throws MyCustomException { //.... } 

我可以得到一些关于此的提示吗?

根据您对我的评论的回答,您将无法仅使用注释来执行此操作。 当然,您可以创建注释并创建一些reflection代码,然后检测并执行某些代码,但这不会对代码进行太多更改,因为在调用方法之前需要调用parser方法,我认为因为你需要在每次调用之前调用解析器方法,这对你没有多大帮助。

如果您需要您提到的行为(自动调用),则需要将注释与一些AOP框架(如Spring(普通Java)或AspectJ(AspectJ代码))结合使用。 然后,您可以设置切入点,每次到达此点时,都可能会执行某些代码。 然后,您可以配置在方法执行之前和/或之后执行某些代码。

如果第一个场景足够,您可以执行以下操作:

记录器:枚举

 public enum Logger { INFO, DEBUG; } 

LogMethodCall:注释

 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention( RetentionPolicy.RUNTIME ) // the annotation will be available during runtime @Target( ElementType.METHOD ) // this can just used in methods public @interface LogMethodCall { Logger logLevel() default Logger.INFO; } 

人:注释类

 public class Person { // will use the default log level (INFO) @LogMethodCall public void foo( int a ) { System.out.println( "foo! " + a ); } @LogMethodCall( logLevel = Logger.DEBUG ) public void bar( int b ) { System.out.println( "bar! " + b ); } } 

Utils:带有log static方法的类(这将执行“解析”)

 public class Utils { public static void log( Object o, String methodName ) { // gets the object class Class klass = o.getClass(); // iterate over its methods for ( Method m : klass.getMethods() ) { // verify if the method is the wanted one if ( m.getName().equals( methodName ) ) { // yes, it is // so, iterate over its annotations for ( Annotation a : m.getAnnotations() ) { // verify if it is a LogMethodCall annotation if ( a instanceof LogMethodCall ) { // yes, it is // so, cast it LogMethodCall lmc = ( LogMethodCall ) a; // verify the log level switch ( lmc.logLevel() ) { case INFO: System.out.println( "performing info log for \"" + m.getName() + "\" method" ); break; case DEBUG: System.out.println( "performing debug log for \"" + m.getName() + "\" method" ); break; } } } // method encountered, so the loop can be break break; } } } } 

AnnotationProcessing:带有代码的类,用于测试注释处理

 public class AnnotationProcessing { public static void main(String[] args) { Person p = new Person(); Utils.log( p, "foo" ); p.foo( 2 ); Utils.log( p, "bar" ); p.bar( 3 ); } } 

当然,您需要改进我的代码以满足您的需求。 这只是一个起点。

有关注释的更多信息:

关于AOP的更多信息:

使用Spring AOP和Java Annotation。 Spring AOP否定了使用Java Reflection编写用于解析Java类的util类的要求。

示例 –

  1. 自定义注释 –

     @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface A { boolean startA() default false; boolean endA() default false; } 
  2. 方面-

      @Aspect public class AAspect { @Pointcut(value = "execution(* *.*(..))") public void allMethods() { LOGGER.debug("Inside all methods"); } @Before("allMethods() && @annotation(A)")` public void startAProcess(JoinPoint pjp, A a) throws Throwable { if (a.startA()) { //Do something } } 
  3. 启用AspectJ –

     @Configuration @EnableAspectJAutoProxy public class AConfig { } 
  4. 在代码中使用 –

     @A(startA = true, endA = true) public void setUp(){ //Do something- logic } 

如前所述,AOP和注释是最佳选择。 我建议使用jcabi-aspects (我是开发人员)的现成机制:

 @Loggable(Loggable.DEBUG) public String load(URL url) { return url.openConnection().getContent(); } 

所有方法调用都将记录到SLF4J。