Spring AOP 注释不起作用
Spring AOP Annotation not working
我有以下方面class:
@Component
@Aspect
public class LoggedRequestAspect {
private static final Logger LOG = LoggerFactory.getLogger(LoggedRequestAspect.class);
@Before("com.application.aspect.pointcut.LoggedRequestPointCut.LogRequest()")
public void logRequest(){
System.out.println("Method Executed!");
LOG.debug("Method Executed!");
}
}
对于注释 class:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoggedRequest {
}
最后是切入点:
public class LoggedRequestPointCut {
@Pointcut("execution(@com.application.aspect.annotation.LoggedRequest * *(..))")
public void LogRequest(){}
}
现在可以肯定的是,我已经在我的控制器中注释了所需的 api 方法:
...
@LoggedRequest
@RequestMapping(value = "/login", method = { RequestMethod.POST })
public @ResponseBody Map<String, Object> login(/* Param List*/){
...
}
正如关于 SO 的许多其他答案所建议的那样。我在 spring 配置中添加了以下内容:
<context:annotation-config/>
...
<context:component-scan base-package="com.application.core"/>
...
<aop:aspectj-autoproxy />
现在这一切都不起作用了。我的意思是在我的 API 调用 /login
时,所需的建议没有执行。
看起来一切正常,但你应该这样写:
<aop:aspectj-autoproxy >
<aop:include name="loggedRequestAspect"/>
</aop:aspectj-autoproxy>
因为您在 spring autoproxy 基础结构中说了这个最终配置,bean 在自动代理过程中考虑了什么。
听到的关键点是,如果你想使用方面来记录方法调用,这很好,但如果你想使用方面来记录 http 调用,它将不起作用,在这种情况下,使用拦截器可能是一个不错的选择。
您可以使用您的 org.springframework.web.servlet.HandlerInterceptor 或 org.springframework.web.context.request.WebRequestInterceptor 实现
然后像这样在 org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter 中注册它:
@Configuration
class MyWebConfiguratio extends WebMvcConfigurerAdapter {
....
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
...
}).addPathPatterns("....");
registry.addInterceptor(new WebMvcConfigurerAdapter() {
....
}).addPathPatterns("....");
}
....
}
在 java 配置中或
<mvc:interceptors>
<bean id="localeChangeInterceptor"
class="com.yourapp.Interceptor""/>
</mvc:interceptors>
在您的 xml 配置文件中使用 mvc 命名空间
希望对您有所帮助
在 Spring 中的 bean 上使用 AOP 时仅应用于同一应用程序上下文中的 bean。
在典型的 Web 应用程序中,您会有一个 ContextLoaderListener
和一个 DispatcherServlet
,它们都会创建一个 ApplicationContext
。 ContextLoaderListener
创建所谓的根应用程序上下文,DispatcherServlet
与根上下文相关的子上下文。
根中的 AOP 配置不影响子上下文中的 bean,子上下文中的 AOP 配置不影响根上下文中的 bean。
现在您已经在根上下文中配置了切面和 <aop:aspectj-autoproxy />
,并将它排除在子上下文中的 bean 之外。这显然是行不通的。将该配置移动(或复制)到子上下文中。
另一件事是你需要基于 class 的代理,因为你没有接口,所以你可能还想将 proxy-target-class="true"
添加到 <aop:aspectj-autoproxy />
元素。
我有以下方面class:
@Component
@Aspect
public class LoggedRequestAspect {
private static final Logger LOG = LoggerFactory.getLogger(LoggedRequestAspect.class);
@Before("com.application.aspect.pointcut.LoggedRequestPointCut.LogRequest()")
public void logRequest(){
System.out.println("Method Executed!");
LOG.debug("Method Executed!");
}
}
对于注释 class:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoggedRequest {
}
最后是切入点:
public class LoggedRequestPointCut {
@Pointcut("execution(@com.application.aspect.annotation.LoggedRequest * *(..))")
public void LogRequest(){}
}
现在可以肯定的是,我已经在我的控制器中注释了所需的 api 方法:
...
@LoggedRequest
@RequestMapping(value = "/login", method = { RequestMethod.POST })
public @ResponseBody Map<String, Object> login(/* Param List*/){
...
}
正如关于 SO 的许多其他答案所建议的那样。我在 spring 配置中添加了以下内容:
<context:annotation-config/>
...
<context:component-scan base-package="com.application.core"/>
...
<aop:aspectj-autoproxy />
现在这一切都不起作用了。我的意思是在我的 API 调用 /login
时,所需的建议没有执行。
看起来一切正常,但你应该这样写:
<aop:aspectj-autoproxy >
<aop:include name="loggedRequestAspect"/>
</aop:aspectj-autoproxy>
因为您在 spring autoproxy 基础结构中说了这个最终配置,bean 在自动代理过程中考虑了什么。 听到的关键点是,如果你想使用方面来记录方法调用,这很好,但如果你想使用方面来记录 http 调用,它将不起作用,在这种情况下,使用拦截器可能是一个不错的选择。
您可以使用您的 org.springframework.web.servlet.HandlerInterceptor 或 org.springframework.web.context.request.WebRequestInterceptor 实现
然后像这样在 org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter 中注册它:
@Configuration
class MyWebConfiguratio extends WebMvcConfigurerAdapter {
....
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
...
}).addPathPatterns("....");
registry.addInterceptor(new WebMvcConfigurerAdapter() {
....
}).addPathPatterns("....");
}
....
}
在 java 配置中或
<mvc:interceptors>
<bean id="localeChangeInterceptor"
class="com.yourapp.Interceptor""/>
</mvc:interceptors>
在您的 xml 配置文件中使用 mvc 命名空间
希望对您有所帮助
在 Spring 中的 bean 上使用 AOP 时仅应用于同一应用程序上下文中的 bean。
在典型的 Web 应用程序中,您会有一个 ContextLoaderListener
和一个 DispatcherServlet
,它们都会创建一个 ApplicationContext
。 ContextLoaderListener
创建所谓的根应用程序上下文,DispatcherServlet
与根上下文相关的子上下文。
根中的 AOP 配置不影响子上下文中的 bean,子上下文中的 AOP 配置不影响根上下文中的 bean。
现在您已经在根上下文中配置了切面和 <aop:aspectj-autoproxy />
,并将它排除在子上下文中的 bean 之外。这显然是行不通的。将该配置移动(或复制)到子上下文中。
另一件事是你需要基于 class 的代理,因为你没有接口,所以你可能还想将 proxy-target-class="true"
添加到 <aop:aspectj-autoproxy />
元素。