[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [aspectj-users] Advice on Constructors With Subclasses
|
Hi James,
nice to hear my code was somewhat useful.
Have you seen the comments on your feature request?
Simone
James Elliott wrote:
> I played with Simone's code a bit, and it does seem to work as described.
>
> Here's the solution I came up with for when the constructor call is
> made within a constructor call.
>
> This solution works assuming that the only places where A or it's
> subclasses are instantiated within the constructor of A or it's
> subclasses are in code that can be woven, which, for my project, is a
> safe assumption.
>
> I made the class abstract so that it can be easily reused whenever
> this pattern is appropriate.
>
> I don't like having the getMyClass() method, but I don't know of a
> good way to get the generic type without it.
>
> I am also caching the return value from isAssignableFrom, since this
> call appears to be relatively expensive in some versions of java.
>
> It's still a bit of a hack, but it seems to fulfill my needs.
>
> public abstract aspect InitializationAspect<T> {
> /* Cache to avoid reflective calls */
> private Map<String, Boolean> isAssignableMap = new HashMap<String, Boolean>();
>
> /**
> * Returns the class highest in the hierarchy. Should be T.
> */
> protected abstract Class<T> getMyClass();
>
> /**
> * The Advice to perform after an object has been instantiated.
> * @param t The object that was created.
> */
> protected abstract void myAdvice(T t);
>
> /**
> * Checks to make sure that the constructor that is executing
> * is the type of the object to be created (i.e. lowest on the stack)
> * and calls myAdvice() if it is. Does nothing if not.
> * @param t The object that was created
> */
> after(T t) : execution(T+.new(..)) && this(t) {
> if (isLastConstructorInChain(getMyClass())) {
> myAdvice(t);
> }
> }
>
> /**
> * Captures any calls to create a new object of type T or it's subtypes
> * that happen within type T or it's subtypes, and calls myAdvice().
> */
> after() returning(T t): call(T+.new()) && withincode(T+.new(..)) {
> myAdvice(t);
> }
>
> /**
> * Returns true if a class' constructor the lowest method call in a
> * chain of constructor calls. If it isn't, return true if the next lowest
> * call is not type T or a subclass of type T, false otherwise.
> * @param clazz The class to look for.
> */
> public boolean isLastConstructorInChain(Class<?> clazz) {
> StackTraceElement[] stackTrace =
> Thread.currentThread().getStackTrace();
>
> // find the first constructor, cause there are a few AspectJ
> internal calls before it
> int acpos = 0;
> while (acpos < stackTrace.length &&
> !stackTrace[acpos].getMethodName().equals("<init>")) {
> acpos++;
> }
> // Check if we run out, should never happen
> if (acpos >= stackTrace.length) {
> return false;
> }
> // Now we have the last call to <init>
> // if the following one is not a constructor (or is not present),
> // we can skip all the checks and return true
> if (acpos + 1 == stackTrace.length ||
> !stackTrace[acpos + 1].getMethodName().equals("<init>")) {
> return true;
> }
> // Otherwise we have to check it the next constructor in the
> // chain is a proper subclass of the current class
> String callingClass = stackTrace[acpos + 1].getClassName();
>
> Boolean isAssignable = isAssignableMap.get(callingClass);
>
> if(isAssignable == null) {
> Class<?> forname = null;
> try {
> forname = Class.forName(callingClass);
> }
> catch (ClassNotFoundException e) {
> e.printStackTrace();
> isAssignable = false;
> }
> isAssignable = !clazz.isAssignableFrom(forname);
>
> isAssignableMap.put(callingClass, isAssignable);
> }
> return isAssignable;
> }
> }
>
> public aspect AAspect extends InitializationAspect<A> {
> protected Class<A> getMyClass() {
> return A.class;
> }
>
> protected void myAdvice(A a) {
> System.out.println("Done:" + a.getClass());
> }
> }
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>
--
Simone Gianni
http://www.simonegianni.it/
CEO Semeru s.r.l.
Apache Committer