如何在Spring Boot中的私有/受保护的RequestMapping上执行AOP

时间:2016-07-19 07:26:13

标签: spring spring-boot aop aspectj

我想在@RequestMapping方法调用下面做AOP,注意hello()方法是 NOT public。

@RestController
class HelloController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    String hello() {
        return "Hello";
    }
}

这是主要类,我添加了@Aspect,@ EnableAspectJAutoProxy注释。

@Aspect
@EnableAspectJAutoProxy(proxyTargetClass = true)
@SpringBootApplication
public class FooServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(FooServiceApplication.class, args);
    }

    @Around("@annotation(requestMapping)")
    public Object around(ProceedingJoinPoint pjp, RequestMapping requestMapping) throws Throwable {
        return pjp.proceed();
    }
}
pom.xml中的

我只是添加下面的依赖项:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

结果是,如果hello()方法是公共的,AOP将正常工作,但如果与上面的例子相同而没有公开声明,则AOP根本不起作用。但是, EnableAspectJAutoProxy 是否会使用CGLIB并拦截受保护/私有方法调用?

1 个答案:

答案 0 :(得分:2)

根据documentation Spring的基于代理的AOP只能拦截public方法

  

由于Spring的AOP框架基于代理的特性,根据定义,受保护的方法既不是针对JDK代理(这不适用),也不针对CGLIB代理(这在技术上可行,但不建议用于AOP)目的)。因此,任何给定的切入点都只能与公共方法匹配!

     

如果您的拦截需要包括受保护/私有方法甚至构造函数,请考虑使用Spring驱动的本机AspectJ编织而不是Spring的基于代理的AOP框架。这构成了具有不同特征的不同AOP使用模式,因此在做出决定之前一定要先熟悉编织。

在决定使用AspectJ编织之前,我建议您通过文档中的appropriate section来帮助您做出决定。

替代

根据您希望实现的目标,您还可以考虑使用Filters

过滤器拦截每个请求,并且有权添加/删除标头,验证,登录等;通常执行通用/应用程序范围的操作。

添加一个只需声明一个类

import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class SomeFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /*execute your logic*/
        if (/* request may proceed*/) {
            chain.doFilter(request,response);
        } else {
            /* write response */
        }
    }
}