自定义 Java 注释以跳过方法执行

Custom Java annotation to skip the method execution

我想创建一个自定义注解来跳过方法执行

这是我的注释代码,带有验证器class

@Target({ METHOD , FIELD , PARAMETER } )
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy={MyValidator .class})
public @interface MyAnnotation {

    String message() default "DEFAULT_FALSE";

    Class<?>[] groups() default{};

    Class<? extends Payload>[] payload() default{};

}

我用验证器试过了。这就是我的验证器的样子

public class MyValidator implements ConstraintValidator<MyAnnotation, String >{

    @Override
    public void initialize(MyAnnotation arg0) {

    }

    @Override
    public boolean isValid(String arg0, ConstraintValidatorContext arg1) {

        if(str=="msg"){
            return true;
        }
        return false;
    }

}

这就是我想要使用的方式 -- 我想在方法级别使用注释并跳过方法执行。

不知道可不可以..求助.

public class Test {



    public static void main(String[] args) {
    Test t = new Test();
        boolean valid=false;

         valid=t.validate();
        System.out.println(valid);

    }

@MyAnnotation(message="msg")
    public boolean validate(){

     // some code to return true or false
    return true;


    }
}

你应该为此使用 AOP。创建一个 AspectJ 项目,然后尝试这样的事情:

MyAnnotation.java:

package moo.aspecttest;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD })
public @interface MyAnnotation
{
    public String value();
}

MyAspectClass.java:

package moo.aspecttest;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;

@Aspect
public class MyAspectClass
{

    @Around("execution(* *(..))")
    public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable
    {
        Method method = MethodSignature.class.cast(point.getSignature()).getMethod();
        String name = method.getName();
        MyAnnotation puff = method.getAnnotation(MyAnnotation.class);
        if (puff != null) {
            System.out.println("Method " + name + " annotated with " + puff.value() + ": skipped");
            return null;
        } else {
            System.out.println("Method " + name + " non annotated: executing...");
            Object toret = point.proceed();
            System.out.println("Method " + name + " non annotated: executed");
            return toret;
        }
    }
}

MyTestClass.java:

package moo.aspecttest;

public class MyTestClass
{

    @MyAnnotation("doh")
    public boolean validate(String s) {
        System.out.println("Validating "+s);
        return true;
    }

    public boolean validate2(String s) {
        System.out.println("Validating2 "+s);
        return true;
    }

    public static void main(String[] args)
    {
        MyTestClass mc = new MyTestClass();

        mc.validate("hello");
        mc.validate2("cheers");

        }
    }
}

当您 运行 时生成的输出:

Method main non annotated: executing...
Method validate annotated with doh: skipped
Method validate2 non annotated: executing...
Validating2 cheers
Method validate2 non annotated: executed
Method main non annotated: executed

我使用了一个非常通用的 aroundAdvice,但如果需要,您可以使用 beforeAdvice。确实,我认为这一点很明确。

其实很简单,可以写的最简单的方面了。 ;-)

你的示例代码的丑陋之处在于它使用了几个 类 而你没有显示源代码,所以我不得不创建虚拟 classes/interfaces 以使你的代码编译.您也没有显示验证器是如何应用的,所以我不得不推测。无论如何,这是一组完全自洽的样本 类:

帮手类:

这只是为了编译所有内容而搭建的脚手架。

package de.scrum_master.app;

public interface Payload {}
package de.scrum_master.app;

public class ConstraintValidatorContext {}
package de.scrum_master.app;

public @interface Constraint {
  Class<MyValidator>[] validatedBy();
}
package de.scrum_master.app;

import java.lang.annotation.Annotation;

public interface ConstraintValidator<T1 extends Annotation, T2> {
  void initialize(T1 annotation);
  boolean isValid(T2 value, ConstraintValidatorContext validatorContext);
}
package de.scrum_master.app;

public class MyValidator implements ConstraintValidator<MyAnnotation, String> {
  @Override
  public void initialize(MyAnnotation annotation) {}

  @Override
  public boolean isValid(String value, ConstraintValidatorContext validatorContext) {
    if ("msg".equals(value))
      return true;
    return false;
  }
}
package de.scrum_master.app;

import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;

import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.*;

@Target({ METHOD, FIELD, PARAMETER })
@Retention(RUNTIME)
@Constraint(validatedBy = { MyValidator.class })
public @interface MyAnnotation {
  String message() default "DEFAULT_FALSE";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}

驱动申请:

如果你想测试一些东西,你不仅需要一个正面的测试用例,还需要一个负面的测试用例。因为您没有提供,所以用户 Sampisa 的答案不是您要找的。顺便说一句,我认为你应该能够自己从中推导出解决方案。你甚至没有尝试。你没有任何编程经验吗?

package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    Application application = new Application();
    System.out.println(application.validate1());
    System.out.println(application.validate2());
  }

  @MyAnnotation(message = "execute me")
  public boolean validate1() {
    return true;
  }

  @MyAnnotation(message = "msg")
  public boolean validate2() {
    return true;
  }
}

看点:

我除了 Sampisa 的之外还添加另一个示例方面的唯一原因是他的解决方案在反射使用方面不是最优的。它很丑而且很慢。我认为我的解决方案更优雅一些。自己看看:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class SkipValidationAspect {
  @Around("execution(@de.scrum_master.app.MyAnnotation(message=\"msg\") boolean *(..))")
  public boolean skipValidation(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    return false;
  }
}

很简单,不是吗?

控制台日志:

true
false

Et voilà - 我想这就是您要找的东西。