Spring MVC 和 AOP:@Controllers 的@Pointcuts 仅适用于测试,不适用于生产

Spring MVC and AOP: @Pointcuts for @Controllers only works in Testing and not for Production

我正在 Web 环境中使用 Spring Framework 4.3.3:

我有两个上下文:

我知道 ServletApplicationContext 包含所有关于 web 端的 beans,例如 @Controller。此外,ServletApplicationContext 能够从 RootApplicationContext 访问所有上下文或 bean,例如 @Service, @Repository 等。直到这里我都很好。

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

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

需要考虑的重要一点是,逆运算不可能

因此

不可能。它有道理并且可以。服务器端不应该访问Web端

关于 AspectJ。我有以下内容:

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {

}

重要的一点:

好的,当我 运行 我的 @Test 方法。

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

而且 AOP 工作正常。我可以通过AOP + logging确认以下过程:

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

而且 AOP 工作正常。我可以通过AOP + logging确认以下过程:

现在用于生产我有:

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 通过 AOP + logging 会发生以下过​​程:

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

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

我已经做了研究,找到了这两个帖子:

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

扫描

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

对于其他 @Bean 关于基础设施的 @Configuration 关系已经解释过 ServletApplicationContext --> RootApplicationContext 是如何工作的。刚用AOP就有这种情况。

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

问题 02:如何让 RootApplicationContext 扫描 AopConfig 并获得预期的生产行为?

注意 如果 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