Можно ли продолжить это с пользовательскими аннотациями? - PullRequest
0 голосов
/ 03 июля 2018

Вот мой код (упрощенный, но работающий), это механизм расчета, пилот, применяющий правила в определенных заказах:

class Rule1 implements IRule{
    doSomethingMethod () {}
}

class Rule2 implements IRule{
    doSomethingMethod () {}
}
...

class Engine1 () {
    Rule1.doSomething();
    Rule2.doSomething();
}

class Engine2 () {
    Rule3.doSomething();
    Rule99.doSomething();
    Rule5.doSomething();
}

Я хотел бы закодировать это с помощью пользовательских аннотаций, потому что моя цель - сделать статистику, из каких движков вызывать какие правила, и я думаю, что это будет проще:

public @Interface Rule (){
    class Rule rule;
}

class Engine1 () {
    @Rule(Rule1.class);
    @Rule(Rule2.class);
}

class Engine2 () {
    @Rule(Rule3.class);
    @Rule(Rule99.class);
    @Rule(Rule5.class);
}

Тогда я мог бы, возможно, выполнить сканирование с помощью org.springframework.context.annotation.ClassPathScanningCandidateCom, чтобы упростить статистику.

Возможно ли это (и как?)? Это хороший способ сделать? Я там по-другому?

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Да, это возможно.

Вы можете определить @Rule аннотацию

  @Target(ElementType.TYPE)
  @Retention(RetentionPolicy.RUNTIME)
  public @interface Rule {
    Class<? extends IRule>[] rule();
  }

И используйте их на своем EngineeX классе

  @Rule(rule = { Rule1.class, Rule2.class })
  public static class Enginee1 {
  }

  @Rule(rule = { Rule2.class, Rule3.class })
  public static class Enginee2 {
  }

Затем мы сканируем класс, чтобы найти, существует ли @Rule. Если да, загрузите их.

public static void load(Class<?> engineeClass) {
  Rule rule = engineeClass.getAnnotation(Rule.class);
  if (rule != null) {
    for (Class<? extends IRule> clz : rule.rule()) {
      try {
        IRule r = clz.newInstance();
        r.run();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
}

Если вы хотите, чтобы они загружались автоматически, как статический блок. Есть несколько подходов.

  1. Добавить статический блок load(EngineeX.class) на каждый EngineeX класс
  2. Если у вас контейнер высокого уровня, например Spring. Вы можете аспектировать процесс загрузки после загрузки класса.
  3. Вручную загружать двигатели, когда вы их используете
  4. Использовать загрузчик пользовательского класса и загружать его после загрузки
0 голосов
/ 03 июля 2018

Мне на ум приходят два подхода,

Я предполагаю, что правило "X" .doSomething () является определением метода в классе, верно? если нет, то отредактируйте исходный код, чтобы получить лучшее представление о том, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...