AspectJ - Creating a global Logger field using an Inter-Type Declaration

I'd like to create an Inter-Type declaration that declares a (static final) Logger instance inside each class.

The constructor should be passed the enclosing class Klazz.class value:

@Aspect
public class LoggerAspect {

    public interface Logger {
    }

    public static class LoggerImpl implements Logger {
        private static final Logger logger = 
          new Logger(thisJoinPoint.getTarget().getClass()/*.getName()*/);
    }

    @DeclareParents(value="com.my.api..*",defaultImpl=LoggerImpl.class)
    private Logger implementedInterface;
}

I wrote the above solution, however I'm unable to use thisJoinPoint outside of an AspectJ advice.

If the Logger default implementation is applied to some class Klazz, how can I modify the above code to successfully pass Klazz.class to the Logger constructor?

Answers


You can declare a static member on any single class via inter-type declaration:

public aspect LoggingAspect {
    static Logger MyClass.someField = Logger.getLogger(MyClass.class.getName());
}

But this is not very flexible because you need to do it for each single class. I just wanted to mention it.

In order to add something which is not technically but effectively a static member to a class, just use per-type association for your logging aspect:

public aspect LoggingAspect
    pertypewithin(org.foo..*)              // per-type association
{
    Logger logger;

    after() : staticinitialization(*) {    // run 1x after class-loading
        logger = Logger.getLogger(
            getWithinTypeName()            // type associated with aspect instance
        );
    }

    pointcut logged() :                    // what to log, e.g. public methods
        execution(public * *(..));         // (pointcut could also be abstract
                                           // and refined in sub-aspects)

    before() : logged() {
        logger.log(...);                   // logging action
    }
}

An example similar to this one - it is a common pattern - can be found in Ramnivas Laddad's excellent book AspectJ in action (2nd edition), chapter 6.2.4. It is also mentioned in the AspectJ documentation.


This answer gives the correct solution, posted below for convenience. Additionally it uses AspectJ annotations which is the preferred notation nowadays.

The developers recently added the annotation API, I presume with the intention of standardising the markup as many other popular libraries like Spring are also doing.

@Aspect("pertypewithin(com.something.*))")
public abstract class TraceAspect {

    Logger logger;

    @Pointcut
    public abstract void traced();

    @Pointcut("staticinitialization(*)")
    public void staticInit() {
    }

    @After(value = "staticInit()")
    public void initLogger(JoinPoint.StaticPart jps) {
        logger = Logger.getLogger(jps.getSignature().getDeclaringTypeName());
    }

    @Before(value = "traced()")
    public void traceThatOne(JoinPoint.StaticPart jps) {
        logger.log(jps.getSignature().getName());
    }
}

Need Your Help

Button change font family in android studio

java android android-studio

I want to change the font family of the button. I tried to change it trying this code:

Linked list delete in C

c linked-list dynamic-allocation

Here's my code, I don't know whats wrong with it. When I "delete" an item in the list using keyboard input, it changes other item's name. Also when I input a name that is not on the list it will de...