После добавления Spring AOP в мой проект Spring Boot следующий аспект создает исключение NullPointerException для компонента автоподключенной службы в моих контроллерах:
@Aspect
@Component
@Slf4j
public class LogRequestAspect {
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping) && execution(public * *(..))")
public Object log(final ProceedingJoinPoint joinPoint) throws Throwable {
final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.currentRequestAttributes())
.getRequest();
final Object proceed = joinPoint.proceed();
log.info(
"{} {} from {},{}",
request.getMethod(),
request.getRequestURI(),
request.getRemoteAddr(),
request.getHeader("X-Forwarded-For"));
return proceed;
}
}
Пример контроллера:
@RestController
public class AController {
@Autowired
AService aService;
@RequestMapping("/doSomething")
private List<Map<String, Object>> doSomething() {
return aService.doSomething();
}
}
Пример сервиса:
@Service
public class AService {
public List<Map<String, Object>> doSomething() {
List<Map<String, Object>> results = new ArrayList<>();
return results;
}
}
Пример конфигурации:
@EnableAspectJAutoProxy
@SpringBootApplication
public class Application implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... strings) {
}
}
Как только я удаляю аспект, все работает отлично. Есть идеи, что мне здесь не хватает?
@Nikolas Да, я только что добавил свою конфигурацию.
Сделайте метод public иначе он не сработает. Вместо того, чтобы передавать вызов метода проксируемому объекту, теперь он вызывается на самом прокси, который не имеет связанных полей. Где, как у обернутого объекта, и вы хотите передать ему вызов метода. Следовательно, сделайте метод public.




Spring AOP по умолчанию работает с использованием прокси. В этом случае используется прокси на основе класса, потому что интерфейс не реализован. Прокси-сервер на основе класса расширяет фактический класс и переопределяет все методы для применения перехватчиков/аспектов.
Однако метод private не может быть переопределен в подклассе, и поэтому ваш метод контроллера будет вызываться на прокси-сервере, а не на проксируемом объекте. Прокси никогда ничего не вводил, поэтому поле aService всегда null там.
Чтобы исправить, создайте метод public или protected, чтобы подкласс мог переопределить метод, и в конечном итоге метод будет вызываться для проксируемого экземпляра вместо прокси.
Вы используете
@EnableAspectJAutoProxy?