Невозможно получить имя класса и метод с помощью @Before Aspect

Я реализовал АОП для ведения журнала.

LoggingAspect

@Aspect
public class LoggingAspect {
  private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LoggingAspect.class);

  @Before("execution(public * *(..))")
  public void logBefore(JoinPoint joinPoint) {
    System.out.println("logBefore() is running!");
    System.out.println("classname : " + joinPoint.getClass().getCanonicalName() + "," + joinPoint.getSignature().getName());
    System.out.println("******");
  }
}

и следующую конфигурацию в app-ctx.xml

<beans xmlns = "http://www.springframework.org/schema/beans"
    xmlns:context = "http://www.springframework.org/schema/context"
    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p = "http://www.springframework.org/schema/p"
    xmlns:aop = "http://www.springframework.org/schema/aop"
    xmlns:tx = "http://www.springframework.org/schema/tx"
    xsi:schemaLocation = "
   http://www.springframework.org/schema/beans     
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context-3.0.xsd
   http://www.springframework.org/schema/aop 
   http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
   http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">
    <context:component-scan
        base-package = "com.pms" />
    <aop:aspectj-autoproxy />
<bean id = "loggingAspect"
        class = "com.pms.advice.LoggingAspect" />
</beans>

но он выводит для всех классов, которые я получаю

logBefore() is running!
classname : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint,getConnection
******

пожалуйста посоветуй

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
617
2

Ответы 2

Я никогда не пойму, почему так много разработчиков вызывают методы на JoinPoint для извлечения конкретной информации, которую они получают бесплатно, просто регистрируя сам экземпляр точки соединения. Здесь есть все: тип точки соединения, сигнатура метода с именем класса и тип возврата. Это то, что вам нужно, если вы действительно хотите знать, что происходит в ваших аспектах. Скрытие информации путем регистрации ее части значительно усложняет отладку. Кроме того, вызов большого количества методов не ускоряет процесс ведения журнала. А потом они жалуются, что АОП "медленный". ;-)

Как бы то ни было, вы хотите использовать здесь joinPoint.getSignature().getDeclaringTypeName(). Вместо этого вы регистрируете класс точки соединения и имя перехваченного метода.

Внимание, joinPoint.getSignature().getDeclaringType() предоставит вам тип динамического прокси, который, вероятно, не тот, который вам нужен.

Обновлять: Если вы используете ((MethodSignature) thisJoinPoint.getSignature()).get*(), у вас есть доступ к еще парочке геттеров:

Method getMethod()
Class getReturnType()
Class[] getParameterTypes()
Class[] getExceptionTypes()
String[] getParameterNames()
String toString()
int getModifiers()
String getName()
String toShortString()
String toLongString()
Class getDeclaringType()
String getDeclaringTypeName()

И, что довольно интересно, в этом случае ((MethodSignature) thisJoinPoint.getSignature()).getDeclaringType() дает вам настоящий класс, а не прокси-класс.

Он все еще не работает Я пробовал ((MethodSignature) thisJoinPoint.getSignature ()). GetDeclaringTypeName () i, e, System.out.println ("****** Имя метода:" + ((MethodSignature) joinPoint.getSignature ()). getDeclaringTypeName ()); но я все еще получаю результат ****** Имя метода: javax.sql.DataSource вместо каждого метода. пожалуйста, порекомендуйте

Aaruhi 05.06.2018 07:29

Конечно, ваш вопрос заключался в том, почему было напечатано неправильное имя класса. Я показал вам, как напечатать правильное имя класса. Так в чем проблема? Если вам нужно имя метода, просто распечатайте его, как будто вы уже знаете, как это сделать - см. Свой собственный пример кода. Теперь, если нет ничего другого, я был бы признателен, если бы вы приняли и проголосовали за мой ответ.

kriegaex 05.06.2018 13:01

проблема в том, что я получаю тот же результат, где я должен получить соответствующее имя класса и метода. Похоже, я чего-то не понимаю или делаю что-то не так Я указал свой код выше

Aaruhi 06.06.2018 07:28

Комментарий не подходит для кода публикации. Пожалуйста, отредактируйте свой вопрос, добавив новый код внизу. И, кстати, я согласен, что вы, должно быть, делаете что-то не так. Однако без понимания вашего кода я не могу сказать что именно. Протестировал свой код, работает. Самый простой способ воспроизвести вашу проблему - опубликовать полный образец проекта на GitHub, чтобы я мог его клонировать и запустить.

kriegaex 10.06.2018 06:22
joinPoint.getSignature (). getDeclaringTypeName () работает для меня и дает имя реализованного класса.
singhpradeep 24.04.2020 15:30

Я могу опоздать на вечеринку, но это может кому-то помочь.

Я считаю, что @Aaruhi хочет, чтобы его реализованные классы регистрировались. Если да, то это поможет:

@Before("execution(* <your_pakage_name>..*.*(..))")
public void logBefore(JoinPoint joinPoint) {
   System.out.println("logBefore() is running!");
   System.out.println("classname : " + joinPoint.getSignature().getDeclaringTypeName() + "," + joinPoint.getSignature().getName());
   System.out.println("******");
}

Это распечатает журналы для всех частных, общедоступных и внутренних методов. Обновите <your_pakage_name>, это позволит вести журнал для всех классов, подпадающих под данный <your_pakage_name>.

joinPoint.getSignature().getDeclaringTypeName() - Это напечатает имя вашего реализующего класса.

ПРИМЕЧАНИЕ - Обновите выражение pointcut до execution(public * <your_pakage_name>..*.*(..)), чтобы включить ведение журнала только для общедоступных методов.

Другие вопросы по теме