AspectJ - Создание глобального поля Logger с использованием объявления между типами
Я хотел бы создать объявление 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;
}
Я написал вышеупомянутое решение, однако я не могу использовать thisJoinPoint
вне AspectJ advice
,
Если реализация Logger по умолчанию применяется к некоторому классу Klazz, как я могу изменить приведенный выше код для успешной передачи Klazz.class в конструктор Logger?
2 ответа
Вы можете объявить статический член для любого отдельного класса через объявление между типами:
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
}
}
Пример, похожий на этот, - это обычный шаблон - можно найти в превосходной книге Рамниваса Ладдада "Аспект J в действии" (2-е издание), глава 6.2.4. Это также упоминается в документации AspectJ.
Этот ответ дает правильное решение, размещенное ниже для удобства. Кроме того, он использует аннотации 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());
}
}