mardi 17 janvier 2017

Spring AOP Target Object Aspect not being called when target object is accessed via reflection

I currently have Spring AOP defining an aspect for logging(Logging Aspect) on a Spring Bean (Target Implementation). When I access the method normally (Regular Access) My Implementation runs and I receive logs. However, when I access my implementation via reflection (Reflection Access) My implementation runs, but I do not receive any logging. I would like to understand why this is and how I can get my reflection based access pattern to get logs. See Reference picture

Basic code flow

Full example: (Note the reflection call actually comes from the parent class)

Parent Class (with reflection call)

public class EventValidationHandler {
    private List<Method> aggregateMethods;

    public EventValidationHandler() {
        aggregateMethods = getMethodsAnnotatedWithAggregateEventHandler(this.getClass());
    }

    public boolean validateEvent(DomainEvent event) throws Exception {
        Class clazz = event.getClass();
        for(Method method : aggregateMethods) {
            for(Class aClass : method.getParameterTypes()) {
                if(clazz.equals(aClass)) {
                    Object response = method.invoke(this, event);
                    return (Boolean) response;
                }
            }
        }
        throw new NoSuchMethodError("Unable to locate event validator method for event type: " + event.getClass().getSimpleName() + ".  Please confirm method is annotated with @" + EventValidator.class.getSimpleName());
    }

    private static List<Method> getMethodsAnnotatedWithAggregateEventHandler(final Class<?> type) {
        final List<Method> methods = new ArrayList<>();
        final List<Method> allMethods = new ArrayList<>(Arrays.asList(type.getDeclaredMethods()));
        for (final Method method : allMethods) {
            if (method.isAnnotationPresent(EventValidator.class)) {
                methods.add(method);
            }
        }
        return methods;
    }
}

Implementation

@Component
@AllArgsConstructor
public class MyEventValidator extends EventValidationHandler {
    private AggregateRepository aggregateRepository;

    @EventValidator
    public boolean isValid(CreateProfileEvent event) {
        if(aggregateRepository.findOne(event.getEmployeeId()) == null) {
            return true;
        }
        return false;
    }

    @EventValidator
    public boolean isValid(ChangePhoneNumberEvent event) {
        if(aggregateRepository.findOne(event.getEmployeeId()) != null) {
            return true;
        }
        return false;
    }
}

Logging Aspect

@Aspect
@Component
public class MyEventValidatorLoggingAspect {
    public static Logger log = LoggerFactory.getLogger(MyEventValidator.class);

    @Pointcut("execution(* com.mcf7.eventsourcing.test.data.events.MyEventValidator.isValid(com.mcf7.eventsourcing.test.data.events.CreateProfileEvent))")
    private void createProfile() {}

    @Before("createProfile()")
    public void logHere(JoinPoint joinPoint) {
        log.info("super cool log of create profile");
    }
}





Aucun commentaire:

Enregistrer un commentaire