john
john

Reputation: 61

Creating Dynamic Advice by Passing in Strategies to Aspect

I am trying to make my advice more dynamic based on the class/method it is providing advice for. Looking for something like this pseudoish code:

class Activity
   private TheAdviceStrategyInterface activityAdviceStrategy = new ActivityAdviceStrategy();

@Entity(adviceStrategy = activityAdviceStrategy)
public void doSomething(ActivityInput ai) { ... }
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Entity {
    public TheAdviceStrategyInterface adviceStrategy();
}
@Aspect
public class TheAdvice {
    @Around("@annotation(entity)")
    public Object doStuff (ProceedingJoinPoint pjp, Entity entity) { 
        ...
        TheAdviceStrategyInterface theStrat = entity.adviceStrategy();
        ....
    }

}

But of course we can not have Objects or Interfaces as annotation parameters.

Any "advice" on how I can implement this? I basically want one Aspect annotation to handle very similar situations, with a slight difference depending on which class is using the annotation.

Upvotes: 1

Views: 93

Answers (1)

dreamcrash
dreamcrash

Reputation: 51523

But of course we can not have Objects or Interfaces as Annotation parameters. Any "advice" on how I can implement this?

1- Create a String parameter in the Entity interface to represent the possible strategies:

@Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Entity {
        public String adviceStrategy();
    }

2- Create a class that implements the factory pattern, for instance:

public class TheAdviceStrategyFactory {
    
   //use getShape method to get object of type shape 
   public TheAdviceStrategyInterface getStrategy(String strategy){
      if(strategy == null){
         return null;
      }     
      if(strategy.equalsIgnoreCase("Strategy1")){
         return new TheAdviceStrategy1();
         
      } else if(strategy.equalsIgnoreCase("Strategy2")){
         return new TheAdviceStrategy2();
      
      return null;
   }
}

with the Classes TheAdviceStrategy1 and TheAdviceStrategy2 implementing the interface TheAdviceStrategyInterface.

Take advantage of both in the advice:

@Aspect
public class TheAdvice {
    @Around("@annotation(entity)")
    public Object doStuff (ProceedingJoinPoint pjp, Entity entity) { 
        ...
        TheAdviceStrategyFactory factory = new TheAdviceStrategyFactory(); 
        TheAdviceStrategyInterface theStrat = factory.getStrategy(entity.adviceStrategy());
        ....
    }

}

Upvotes: 1

Related Questions