I have an aspect which should fire only once after any non-default constructor has been executed
(i.e. after the object has been fully constructed). The purpose is simply to fire a method validating
the internal state within the Entity just constructed.
a) All non-default constructors
b) The constructor only in the concrete subclass - i.e. not the constructors of all superclasses within the inheritance hierarchy.
c) Only the constructors for (a) and (b) when the type of the class being constructed - or any of its supertypes - implement the Validatable interface as per below.
The pointcut definition below works for [a] and [c] - but it fires for all constructors within the
inheritance hierarchy of the class being constructed (i.e. after the constructor of the superclass is
executed but before the statements within the constructor of the subclass are executed).
What have I missed?
How should the Pointcut _expression_ be to fire only once after the object itself is constructed?
@Aspect
public class ValidationAspect {
// Our log
private static final Logger log = LoggerFactory.getLogger(ValidationAspect.class);
/**
* Pointcut defining a default constructor within any class.
*/
@Pointcut("initialization(*.new())")
void anyDefaultConstructor() {
}
/**
* Defines a Pointcut for any constructor to a class implementing Validatable -
* except default constructors (i.e. those having no arguments).
*
* @param joinPoint The currently executing joinPoint.
* @param aValidatable The Validatable instance just created.
*/
@Pointcut(value = "initialization(com.teliasonera.tindra.core.common.validation.Validatable+.new(..)) "
+ "&& this(aValidatable) "
+ "&& !anyDefaultConstructor()", argNames = "joinPoint, aValidatable")
void anyNonDefaultConstructor(final JoinPoint joinPoint, final Validatable aValidatable) {
}
/**
* Validation aspect, performing its job after calling any constructor except
* non-private default ones (having no arguments).
*
* @param joinPoint The currently executing joinPoint.
* @param validatable The validatable instance just created.
* @throws InternalStateValidationException
* if the validation of the validatable failed.
*/
@After(value = "anyNonDefaultConstructor(joinPoint, validatable)", argNames = "joinPoint, validatable")
public void performValidationAfterCompoundConstructor(final JoinPoint joinPoint, final Validatable validatable)
throws InternalStateValidationException {
… [ code omitted ] …
}
}
--
// Bästa hälsningar,
// [sw. "Best regards,"]
//
// Lennart Jörelid, Systems Architect
// cell: +46 708 507 603
// skype: jgurueurope