How can I access the parameters given in the Java aspect?

I have an annotation called "@ProgressCheck" that we can put on the controller to check the progress of the application. If the app has already been submitted or is late, it will present the user with a page appropriate for this situation.

Annotation interface:

@Retention(RetentionPolicy.RUNTIME)
public @interface ProgressCheck {
}

      

The "implementation" of this annotation looks like this:

@Around("execution(* *(..)) && args(session,..) && @annotation(com.foo.aspects.progress.ProgressCheck)")
public Object progressCheck(ProceedingJoinPoint pjp, HttpSession session) throws Throwable {

    Applicant applicant = this.applicationSessionUtils.getApplicant(session);
    Application application = this.applicationSessionUtils.getApplication(session);

    switch (this.applicantService.getProgress(applicant)) {
    case SUBMITTED:
        return this.modelAndViewFactory.gotoStatusPage(applicant, application);

    case LATE:
        return this.modelAndViewFactory.gotoDeadlineMissed(applicant, application);

    default:
    case IN_PROGRESS:
        return pjp.proceed();
    }
}

      

Based on the values ​​in the session and the database, the "implementation" of the annotation allows the user to navigate to the controller or redirect them to another ModelAndView as needed.

I would like to provide annotation options and then in this "implementation" logic use those options to further customize the solution. How from this logic, without knowing where the annotation is applied, can I access these parameters? Or is there another approach I should be using?

+3


source to share


1 answer


The trick is to query the JoinPoint object to annotate the method (or class, or whatever) that has been annotated. This is a glue that I could not understand.

Here's an example. First, the aspect interface. This annotation will only be applied to methods.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DayOfWeek {

    public String[] names();

}

      

Now the implementation of the aspect:

@Aspect
public class DayOfWeekAspect {

    public DayOfWeekAspect() {
    }

    @Around("execution(* *(..)) && args(session,..) && @annotation(edu.berkeley.jazztwo.aspect.ams.roles.DayOfWeek)")
    public Object dayOfWeek(ProceedingJoinPoint joinPoint, HttpSession session) throws Throwable {

        String[] names = this.getNames(this.getAnnotatedMethod(joinPoint));

        for (String name : names) {
            System.out.println("DayOfWeek:   " + name);
        }

        // Do whatever you want with the aspect parameters
        if (checkSomething(names)) {
            // in some cases, go to a different view/controller
            return new ModelAndView(...);
        }

        // Just proceed into the annotated method
        return joinPoint.proceed();
    }

    private Method getAnnotatedMethod(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        return methodSignature.getMethod();
    }

    private String[] getNames(Method method) {
        DayOfWeek aspect = method.getAnnotation(DayOfWeek.class);
        if (aspect != null) {
            return aspect.names();
        }
        return new String[0]; // no annotation, return an empty array
    }
}

      



Then apply aspect to some method

@DayOfWeek(names = {"Monday", "Wednesday", "Friday"})
@RequestMapping(value = "foo", method = RequestMethod.GET)
public ModelAndView foo(...) {
    ...
}

      

Then if you are like me, you will scratch your head and wonder why this is not working. You finally remember (if using XML config) that you need to instantiate the bean somewhere in your config:

<bean id="dayOfWeekAspect" class="com.foo.bar.DayOfWeekAspect" />     

      

THEN you can call foo and it should print on Monday, Wednesday and Friday.

0


source







All Articles