Spring MVC和AOP:@控制器的@PointCuts只能在测试中工作,不能用于生产 [英] Spring MVC and AOP: @Pointcuts for @Controllers only works in Testing and not for Production

查看:0
本文介绍了Spring MVC和AOP:@控制器的@PointCuts只能在测试中工作,不能用于生产的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Web环境中使用Spring框架4.3.3:

我有两个上下文:

  • RootApplicationContext
  • ServletApplicationContext
我知道ServletApplicationContext包含了关于Web端的所有Bean,例如@Controller。此外,ServletApplicationContext能够从RootApplicationContext访问所有上下文或Bean,例如@Service, @Repository等。

注意它也适用于@Configuration类。(基础设施)

因此,在前面的介绍中,我们可以这样思考:

  • ServletApplicationContext-->RootApplicationContext

需要考虑的重要一点是,反转不可能

因此

  • RootApplicationContext-->ServletApplicationContext

不可能。这是有道理的,也是可以的。服务器端不应访问Web端

关于AspectJ。我有以下信息:

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {

}

这里有一点很重要:

  • AopConfigRootApplicationContext扫描
    • 我相信ServletApplicationContext可以通过RootApplicationContext
    • 访问引用@Configuration
当我运行我的@Test方法时,确定。

当我从服务器端执行测试类时,我使用

  • @ContextConfiguration(classes={RootApplicationContext.class} )
    • RootApplicationContext

并且AOP工作得很好。我可以通过AOP + logging以下流程确认:

  • @Service->@Repository

当我从Web端执行测试类时,我使用:

  • @ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})
    • RootApplicationContextServletApplicationContext

并且AOP工作得很好。我可以通过AOP + logging以下流程确认:

  • @Controller->@Service->@Repository

现在我有:

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootApplicationContext.class};
    }

   @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{ServletApplicationContext.class};
    }
但是,当我为.war文件导出项目并通过URL/URI执行时,预期的行为或过程运行良好。但是关于AOP,通过AOP + logging会发生以下过程:

  • @Service->@Repository

@Controller不显示输出。预期流程应为:

  • @Controller->@Service->@Repository

那么为什么在测试中起作用而在生产中不起作用?

我已经做了一个调查,我找到了这两个帖子:

实际上他们说@Configuration@EnableAspectJAutoProxy类应该通过ServletApplicationContext而不是通过RootApplicationContext

进行扫描

即使这是真的(根据新的实验),也要考虑在没有Web环境的情况下测试服务器端。

对于通过@Configuration有关基础设施的其他@Bean,已经解释了ServletApplicationContext --> RootApplicationContext的工作方式。仅AOP就有这种情况。

问题01:为什么会有这种行为?

问题02:如何保持AopConfigRootApplicationContext扫描并获得预期的生产行为?

注意如果AopConfigServletApplicationContext扫描。以下测试内容对服务器端@ContextConfiguration(classes={RootApplicationContext.class, AopConfig.class} )有效,强制。请参阅添加的AopConfig.class,但我认为AopConfig应该由RootApplicationContext扫描。

推荐答案

答案是测试环境中的@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})和生产环境中的上下文继承不是一回事。 在测试环境中,您可以将RootApplicationContextServletApplicationContext作为测试应用程序上下文的一部分。在生产中使用继承,而不是您在问题中描述的简单包含。

似乎来自父上下文的BeanFactoryPostProcessor(在您的情况下是@EnableAspectJAutoProxy)没有应用到子上下文。若要使其在生产中运行,还必须在子上下文中显式定义@EnableAspectJAutoProxy

在这种情况下,Spring上下文定义应该如下所示:

@Configuration
@Import(AopConfig.class)
public class RootApplicationContext {
    ...
}

@Configuration
@Import(AopConfig.class)
public class ServletApplicationContext {
    ...
}

@Configuration
@ComponentScan(basePackageClasses={AopConfig.Class, ...})
public class RootApplicationContext {
    ...
}

@Configuration
@ComponentScan(basePackageClasses={AopConfig.Class, ...})
public class ServletApplicationContext {
    ...
}

Related Task

这篇关于Spring MVC和AOP:@控制器的@PointCuts只能在测试中工作,不能用于生产的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆