AspectJ - 使用Inter-Type声明创建全局Logger字段

Kom*_*ave 3 eclipse logging aspectj global class

我想创建一个Inter-Type声明,声明每个类中的(静态最终)Logger实例.

应该传递构造函数的封闭类Klazz.class值:

@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;
}
Run Code Online (Sandbox Code Playgroud)

我写了上面的解决方案,但是我无法在thisJoinPointAspectJ之外使用advice.

如果将Logger默认实现应用于某些类Klazz,如何修改上述代码以成功将Klazz.class传递给Logger构造函数?

kri*_*aex 7

您可以通过类型间声明在任何单个类上声明静态成员:

public aspect LoggingAspect {
    static Logger MyClass.someField = Logger.getLogger(MyClass.class.getName());
}
Run Code Online (Sandbox Code Playgroud)

但这不是很灵活,因为你需要为每个单独的类做这件事.我只是想提一下.

为了在技术上添加但实际上是静态成员的类,只需对日志记录方面使用per-type关联:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

类似于这个的一个例子 - 它是一种常见的模式 - 可以在Ramnivas Laddad的优秀书籍AspectJ在行动(第2版),第6.2.4章中找到.AspectJ文档中也提到了它.

  • 因此,在你接受了我的初步答案,甚至通过编辑你的问题来承认它是正确的之后,你现在不接受它只是因为我不同意你关于它是"更现代"还是只是不同?这有多不公平?感谢您让我们非常"值得"回答并与您讨论细节. (3认同)