3

我想创建一个 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;
}

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

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

4

2 回答 2

7

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

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

但这不是很灵活,因为您需要为每个班级都这样做。我只是想提一下。

为了向一个类添加一些技术上不是但实际上是静态成员的东西,只需为您的日志记录方面使用每个类型的关联:

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
    }
}

在 Ramnivas Laddad 的优秀著作AspectJ in action (2nd edition)的第 6.2.4 章中可以找到一个与此类似的示例 - 这是一种常见模式。AspectJ 文档中也提到了它。

于 2012-08-26T02:38:11.293 回答
3

这个答案给出了正确的解决方案,为方便起见,贴在下面。此外,它使用 AspectJ 注释,这是当今的首选表示法。

开发人员最近添加了注释 API,我想是为了标准化标记,就像 Spring 等许多其他流行的库一样。

@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());
    }
}
于 2012-08-26T14:57:42.733 回答