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,它们都会创建一个 ApplicationContextContextLoaderListener 创建所谓的根应用程序上下文,DispatcherServlet 与根上下文相关的子上下文。

根中的 AOP 配置不影响子上下文中的 bean,子上下文中的 AOP 配置不影响根上下文中的 bean。

现在您已经在根上下文中配置了切面和 <aop:aspectj-autoproxy />,并将它排除在子上下文中的 bean 之外。这显然是行不通的。将该配置移动(或复制)到子上下文中。

另一件事是你需要基于 class 的代理,因为你没有接口,所以你可能还想将 proxy-target-class="true" 添加到 <aop:aspectj-autoproxy /> 元素。