Ведение журнала AOP: @Aspect не регистрирует ошибку в консоли для конфигурации log4j по умолчанию

#java #spring #logging #spring-aop

#java #spring #ведение журнала #spring-aop

Вопрос:

Я новичок в Spring и пытаюсь реализовать Spring AOP, используя log4j для регистрации ошибок в консоли. Пожалуйста, обратите внимание, что у меня нет log4j.xml в моем проекте, но это должно быть нормально, поскольку я просто хочу зарегистрировать ошибку в консоли, используя концепцию Spring AOP.

Ниже приведен мой код, и когда я запускаю это, я вижу трассировку стека исключений в консоли, но я не вижу своего LoggingAspect.java регистрирует ошибку в консоли, как и должно быть.

Я попытался добавить статический блок в LoggingAspect.java чтобы напечатать некоторый текст в консоли с помощью System.out.println(), но он не печатается.

SpringConfig.java

 package exercise5.com.aadi.configuration;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "exercise5.com.aadi.service")
public class SpringConfig {
}
  

LoggingAspect.java

 package exercise5.com.aadi.utility;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;


@Aspect
@Component
public class LoggingAspect {

    @AfterThrowing(pointcut = "execution(* exercise5.com.aadi.service.*Impl.*(..))", throwing = "exception")
    public void logExceptionFromService(Exception exception) throws Exception {
        Logger logger = LogManager.getLogger(this.getClass());
        logger.error(exception);
    }
}
  

Мое исключение исходит из DAO

InsuranceServiceImpl.java

 package exercise5.com.aadi.service;

...
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

...

@Service(value = "insuranceService")
public class InsuranceServiceImpl implements InsuranceService {

    ...

    @Override
    public List<PolicyReport> getReport(String policyType) throws Exception {
        ...

        if (filteredPolicy.isEmpty())
            throw new Exception("Service.NO_RECORD");

        ...

    }

    ...
}
  

Ниже приведено сообщение консоли, которое я получаю

 ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2
Exception in thread "main" java.lang.Exception: Service.NO_RECORD
    at exercise5.com.aadi.service.InsuranceServiceImpl.getReport(InsuranceServiceImpl.java:43)
    at exercise5.com.aadi.ui.UserInterface.generateReport(UserInterface.java:45)
    at exercise5.com.aadi.ui.UserInterface.main(UserInterface.java:20)
  

Но чего я ожидаю, так это

 ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2
Exception in thread "main" 02:03:52.656 [main] ERROR exercise5.com.aadi.service.InsuranceServiceImpl
java.lang.Exception: Service.NO_RECORD
    at exercise5.com.aadi.service.InsuranceServiceImpl.getReport(InsuranceServiceImpl.java:56) [bin/:?]
    at exercise5.com.aadi.ui.UserInterface.generateReport(UserInterface.java:45) [bin/:?]
    at exercise5.com.aadi.ui.UserInterface.main(UserInterface.java:20) [bin/:?]
java.lang.Exception: Service.NO_RECORD
    at exercise5.com.aadi.service.InsuranceServiceImpl.getReport(InsuranceServiceImpl.java:56)
    at exercise5.com.aadi.ui.UserInterface.generateReport(UserInterface.java:45)
    at exercise5.com.aadi.ui.UserInterface.main(UserInterface.java:20)
  

Обратите внимание, что журнал исключений должен быть дважды. Первое из Spring AOP LoggingAspect.java и вторая — это обычная трассировка стека исключений.

Кто-нибудь может мне помочь, почему я не получаю первое сообщение?

Ответ №1:

Вы указываете

 @ComponentScan(basePackages = "exercise5.com.aadi.service")
  

Это означает, что ваш LoggingAspect @Component не будет обнаружен Spring, потому что он находится под

 exercise5.com.aadi.utility
  

В остальном ваша конфигурация AOP кажется правильной.

Комментарии:

1. Большое спасибо. Это устранило проблему, когда я добавил пакет LoggingAspect class’ в базовые пакеты класса SpringConfig.

2. Хотя у меня возникла другая проблема. ctx.getBean(InsuranceServiceImpl.class) выдает мне исключение NoSuchBeanDefinitionException. в то время как ctx.getBean("insuranceService") работает абсолютно нормально. Есть какие-нибудь подсказки?

3. @Aadi InsuranceServiceImpl кажется конкретной реализацией, возможно, вам нужно запросить относительный базовый интерфейс.

4. Вау! не могу поверить. Это исправлено при добавлении ctx.getBean(InsuranceService.class) . Ты гений. Большое спасибо. Но я не понимаю причину, почему InsuranceServiceImpl.class не сработало? В каком сценарии мне нужно сделать, как getBean(… Service.class )? или getBean(….ServiceImpl.class ) всегда неправильно?

5. @Aadi Это зависит. Вопрос, который вам нужно задать себе, заключается в том, реализует ли этот класс интерфейс? Если это происходит, обычно правильным для запроса является интерфейс. Если этого не произойдет, вы вынуждены использовать конкретный класс.