【问题标题】:Spring MVC and AOP: @Pointcuts for @Controllers only works in Testing and not for ProductionSpring MVC 和 AOP:@Controllers 的 @Pointcuts 仅适用于测试,不适用于生产
【发布时间】:2016-09-26 04:13:56
【问题描述】:

我正在 Web 环境中使用 Spring Framework 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})
    • RootApplicationContext ServletApplicationContext

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 执行 Controller 时,预期的行为或过程可以正常工作。但是关于通过AOP + logging的AOP会发生以下过​​程:

  • @Service -> @Repository

@Controller 不会出现在输出中。预期的流程应该是:

  • @Controller -> @Service -> @Repository

那么为什么在测试中工作而不是在生产中呢?

我已经做了一个研究,我发现了这两个帖子:

实际上他们说带有@EnableAspectJAutoProxy@Configuration 类应该通过ServletApplicationContext 而不是通过RootApplicationContext 进行扫描

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

对于其他关于基础设施的@Beans,通过@Configuration 已经解释了关于ServletApplicationContext --&gt; RootApplicationContext 的关系如何按预期工作。只是用AOP才有这种情况。

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

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

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

【问题讨论】:

    标签: spring spring-mvc spring-aop spring-java-config spring-aspects


    【解决方案1】:

    答案是测试环境中的@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

    【讨论】:

    • 您好,您的意思是@EnableAspectJAutoProxy 声明了两次?它适用于两种情况?想知道它是否对性能有一些影响。另外,我记得一个关于测试的注释context inheritance。是的,它是@ContextHierarchy。我已经确认有两个@EnableAspectJAutoProxy 的功能。我将通过 JIRA 检查是否是错误...也许会通过 @Configuration 添加一些特别的东西,并按预期工作。
    • 酷!有趣的是春天会说什么
    • 目前我从 RootApplicationContextServletApplicationContext 扫描两次 unique 类和 @EnableAspectJAutoProxy
    • 您是否尝试过像我建议的那样在两种情况下都使用@EnableAspectJAutoProxyThis 答案确认 @EnableAspectJAutoProxy 不会影响子 servlet 上下文。
    • 可能这是一个离题,但我不确定在这种情况下@ComponentScan 是否比@Import 更好。如果您对为什么感兴趣,那么我可以在单独的问题中回答... :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 2011-09-21
    • 2012-07-23
    相关资源
    最近更新 更多