我想创建一个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;
}
我编写了上述解决方案,但是我无法在AspectJ thisJoinPoint
之外使用advice
。
如果将Logger默认实现应用于某个类Klazz,如何修改上述代码以成功将Klazz.class传递给Logger构造函数?
答案 0 :(得分:7)
您可以通过类型间声明在任何单个类上声明静态成员:
public aspect LoggingAspect {
static Logger MyClass.someField = Logger.getLogger(MyClass.class.getName());
}
但这不是很灵活,因为你需要为每一个班级做这件事。我只是想提一下。
为了在类中添加一些技术上不是有效的静态成员,只需对日志记录方面使用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
}
}
类似于这一个例子 - 它是一种常见的模式 - 可以在Ramnivas Laddad的优秀书籍AspectJ in action (2nd edition)中找到,第6.2.4章。它也在AspectJ documentation中提到。
答案 1 :(得分:3)
This answer提供了正确的解决方案,方便以下发布。此外,它使用AspectJ注释,这是当今首选的符号。
开发人员最近添加了注释API,我认为其目的是标准化标记,就像许多其他流行的库一样。
@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());
}
}