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

时间:2016-09-26 04:13:56

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

我在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可以通过访问@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 - &gt; @Repository

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

  • @Controller - &gt; @Service - &gt; @Repository

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

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

实际上他们说@Configuration @EnableAspectJAutoProxy课程ServletApplicationContext应该通过RootApplicationContext进行扫描,而不是通过@Bean进行扫描

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

对于@Configuration关于基础设施的其他ServletApplicationContext --> RootApplicationContext,已经解释过的关于AopConfig的关系有效。只是与AOP有这种情况。

问题01 :为什么会出现这种情况?

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

如果ServletApplicationContext扫描@ContextConfiguration(classes={RootApplicationContext.class, AopConfig.class} ),则

注意。以下有关测试的服务器端AopConfig.class的有效和强制。请参阅AopConfig的添加内容,但我认为应RootApplicationContext扫描while True: if b == maxpass and booking == "b" or booking == "book": print ("Sorry but the flight you want is currently fully booked. Sorry for Inconviniance") print ("Welcome to Flight Booking Program") print ("Please enter the flight number you want to book/cancel with? (Case Sensitve)") flight = input()

1 个答案:

答案 0 :(得分:4)

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