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})
在测试环境中和生产环境中的继承不是一回事。在测试环境中,您包括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 {
...
}