2016-07-19 137 views
1

我想在下面的@RequestMapping方法調用上做AOP,注意hello()方法是不是 public。如何在Spring Boot中使用Private/protected RequestMapping執行AOP

@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> 

的結果是,如果你好()方法是公共的,在AOP只會工作正常,但如果同樣的例子以上未經公開聲明,AOP完全不起作用。但不是EnableAspectJAutoProxy將使用CGLIB並可以攔截受保護/私有方法調用?

+0

不,不可能的,這是基於代理的AOP的限制。 –

+0

@ M.Deinum我檢查了[aop上的Spring Boot文檔](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-pointcuts-designators) ,可以使用Spring驅動的[native AspectJ weaving](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw)到解決這個問題,但不推薦,對不對? –

回答

2

按照documentation Spring的基於代理的AOP只能攔截public方法

由於Spring的AOP框架的基於代理的性質,保護的方法是通過定義不攔截,既不是JDK代理(其中本不適用),也不適用於CGLIB代理(在技術上可行但不推薦用於AOP目的)。因此,任何給定的切入點將僅與公共方法匹配!

如果您的攔截需求包含protected/private方法或構造函數,請考慮使用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 */ 
     } 
    } 
} 
+0

感謝您的回覆,我已經注意到了上面提到的Spring文檔。由於對Spring不太熟悉,有沒有辦法在Spring Context中攔截RestController來進行定製而不使用AOP,而是利用Spring自己的接口或回調? –

+0

這真的取決於**「做定製」**的意思:)。您可能還想閱讀過濾器,以查看它是否適合您的自定義需求。 (更新的答案) – Matyas