Spring MVC和AOP:@控制器的@PointCuts只能在测试中工作,不能用于生产 [英] Spring MVC and AOP: @Pointcuts for @Controllers only works in Testing and not for Production
问题描述
我在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 {
}
这里有一点很重要:
- 此
AopConfig
由RootApplicationContext
扫描- 我相信
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执行时,预期的行为或过程运行良好。但是关于AOP,通过AOP + logging
会发生以下过程:
@Service
->@Repository
@Controller
不显示输出。预期流程应为:
@Controller
->@Service
->@Repository
那么为什么在测试中起作用而在生产中不起作用?
我已经做了一个调查,我找到了这两个帖子:
实际上他们说@Configuration
和@EnableAspectJAutoProxy
类应该通过ServletApplicationContext
而不是通过RootApplicationContext
即使这是真的(根据新的实验),也要考虑在没有Web环境的情况下测试服务器端。
对于通过@Configuration
有关基础设施的其他@Bean
,已经解释了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})
和生产环境中的上下文继承不是一回事。
在测试环境中,您可以将RootApplicationContext
和ServletApplicationContext
作为测试应用程序上下文的一部分。在生产中使用继承,而不是您在问题中描述的简单包含。
似乎来自父上下文的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 {
...
}
这篇关于Spring MVC和AOP:@控制器的@PointCuts只能在测试中工作,不能用于生产的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!