0

Here is my code (simplified but working), it's a calculation engine, pilot by applying rules in certain orders:

class Rule1 implements IRule{
    doSomethingMethod () {}
}

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

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

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

I would like to code this with custom Annotations, because my goal is to make statistics from which engines call which rules, and I think it will be more easy:

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);
}

Then I could maybe scan with org.springframework.context.annotation.ClassPathScanningCandidateCom to make statistics more easy.

Is this possible (and how?) ? Is this the goodway to do ? I there another way ?

Tyvain
  • 2,640
  • 6
  • 36
  • 70
  • 1
    None of the `Engine` classes show valid Java code. What are you trying to do? – flakes Jul 03 '18 at 01:54
  • https://stackoverflow.com/questions/10205261/how-to-create-custom-annotation-with-code-behind – raviiii1 Jul 03 '18 at 02:08
  • @flakes I simplified the code, but the idea is to 'inject' the code of each rule to have it executed in the right order. The main goal is to be able to make easy statistics with another program, that could scan my project, looking for all rules annotations in engines classes. Another way to do it, would be to read my project (with FileReader) and read the content of the engines classes... but it's less 'elegant'... no ? – Tyvain Jul 03 '18 at 02:24
  • 1
    You still haven't explained what a rule is, or how rules get used, or how you want some other application to use them. When you say "make easy statistics with another program", that really doesn't mean anything to anyone without context for your application. Do you want to create these rules as a library? Who calls the engine class? Why do you need a special syntax to "inject" them? Could you just use a standard IoC library like Guice or Spring.. if not why not? I suggest that you re-work the original question to be more clear on what the application does, and who the actors are. – flakes Jul 03 '18 at 02:35
  • It's possible that you could generate the code using an annotation processor. There's a good tutorial at https://deors.wordpress.com/2011/09/26/annotation-types/. – Radiodef Jul 03 '18 at 02:52

1 Answers1

0

Yes, it is possible.

You can define the @Rule annotation

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

And use them on your EngineeX class

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

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

Then we scan the class to find if there is @Rule. If yes, load them.

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();
      }
    }
  }
}

If you want them loaded automically like static block. There are serveral approaches.

  1. Add static block load(EngineeX.class) on each EngineeX class
  2. If you have a high level container, like Spring. You can aspect the load process after the class loaded.
  3. Manually load the enginee when you use them
  4. Use a custom class loader and load enginee after load it
Dean Xu
  • 4,438
  • 1
  • 17
  • 44