Why Private Controller Methods Fail with Spring AOP: The Hidden CGLIB Limitation
This article explains why private controller methods in Spring Boot fail when AOP logging is enabled, revealing that CGLIB proxies cannot intercept private methods, which leads to null service injection, and provides code examples and a final conclusion.
Background: In a code review the author asked whether controller request methods can be private or protected instead of public.
An example environment is simulated with a service interface, its implementation, and a RestController containing a public endpoint /testA and a private endpoint /testB. Both return the string "业余草".
public interface TestService {
String getTestString();
}
@Service("testService")
public class TestServiceImpl implements TestService {
@Override
public String getTestString() {
return "业余草";
}
}
@RestController
public class MainController {
@Autowired
private TestService service;
@RequestMapping("/testA")
public String testA() {
return service.getTestString();
}
@RequestMapping("/testB")
private String testB() {
return service.getTestString();
}
}Without AOP, both /testA and /testB return the expected string. Adding an AOP logging aspect changes the behavior.
@Aspect
@Component
public class WebLogAspect {
private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
@Pointcut("execution(public * com.spring.controller..*.*(..))")
public void controllerLog(){}
@Before("controllerLog()")
public void logBeforeController(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
logger.info("*************URL : " + request.getRequestURL().toString());
logger.info("*************HTTP_METHOD : " + request.getMethod());
logger.info("*************IP : " + request.getRemoteAddr());
}
}After adding the aspect, /testA still works, but /testB throws a NullPointerException because the injected service is null.
Changing the pointcut to include private methods ( execution(private* com.spring.controller..*.*(..))) does not solve the problem; the private method still fails.
Conclusion: When AOP is active, Spring Boot 2.1.4 uses CGLIB proxies, which create a subclass of the target class. Private methods are not inherited by the subclass if it resides in a different package, so CGLIB cannot proxy them, leading to null injection.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
