Spring MVC和AOP:@Controllers的@Pointcuts仅在测试中起作用,而在生产环境中不起作用


问题内容

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

我有两种情况:

  • RootApplicationContext
  • ServletApplicationContext

我知道例如ServletApplicationContext包含有关Web端的所有bean
@Controller。而且ServletApplicationContext能够访问所有上下文或来自RootApplicationContext例如@Service, @Repository等等的bean 。到这里为止,我还不错。

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

因此,通过前面的介绍,我们可以通过以下方式进行思考:

  • ServletApplicationContext -> RootApplicationContext

采取在考虑什么重要的是,倒数是 不是 可能。

因此

  • RootApplicationContext -> ServletApplicationContext

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

关于AspectJ。我有以下几点:

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {

}

这里重要一点:

  • AopConfig是通过扫描RootApplicationContext
    • 我相信ServletApplicationContext可以@Configuration通过访问RootApplicationContext

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

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

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

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

  • @Service -> @Repository

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

  • @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 AOP + logging的过程如下:

  • @Service -> @Repository

@Controller没有出现在输出中。预期的流程应为:

  • @Controller-> @Service->@Repository

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

实际上,他们说应该通过而不是通过扫描@Configuration@EnableAspectJAutoProxy``ServletApplicationContext``RootApplicationContext

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

对于其他@Bean有关基础结构的文章,通过@Configuration已经说明的ServletApplicationContext --> RootApplicationContext工作关系可以预期。这种情况仅与AOP有关。

问题01 :为什么要这样?

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

注意 是否AopConfig被扫描ServletApplicationContext。关于测试的以下内容对于服务器端是有效的
和强制性@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 {
    ...
}

相关任务