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

后端 未结 2 1712
滥情空心
滥情空心 2021-01-06 21:58

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

相关标签:
2条回答
  • 2021-01-06 22:13

    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.

    0 讨论(0)
  • 2021-01-06 22:22

    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());
        }
    }
    
    0 讨论(0)
提交回复
热议问题