首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring和AOP:@Pointcuts for @Controller只在测试中工作,而不用于生产。

Spring和AOP:@Pointcuts for @Controller只在测试中工作,而不用于生产。
EN

Stack Overflow用户
提问于 2016-09-26 04:13:56
回答 1查看 1.1K关注 0票数 2

我正在Web环境中使用SpringFramework4.3.3:

我有两个背景:

  • RootApplicationContext
  • ServletApplicationContext

我知道ServletApplicationContext包含关于web端的所有bean,例如@Controller。此外,ServletApplicationContext能够访问来自RootApplicationContext的所有上下文或bean,例如@Service, @Repository等。

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

因此,在前面的介绍中,我们可以这样想:

  • ServletApplicationContext -> RootApplicationContext

重要的是要考虑的是,逆是,而不是

因此

  • RootApplicationContext -> ServletApplicationContext

是不可能的。它是有意义的,是可以的。服务器端不应该访问Web端

关于AspectJ。我有以下几点:

代码语言:javascript
复制
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {

}

这里有一点是很重要的:

  • AopConfigRootApplicationContext 扫描。
    • 我相信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

现在为了生产,我有:

代码语言:javascript
复制
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

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

我已经做了一项研究,我发现这两篇文章:

实际上,他们说带有@EnableAspectJAutoProxy@EnableAspectJAutoProxy类应该通过ServletApplicationContext而不是RootApplicationContext进行扫描。

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

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

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

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

Note如果AopConfigServletApplicationContext扫描。下面的测试是有效的和服务器端的强制性( @ContextConfiguration(classes={RootApplicationContext.class, AopConfig.class} ) )。请参阅添加的AopConfig.class,但我认为AopConfig应该由RootApplicationContext扫描。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-26 05:32:22

答案是,测试环境中的@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})和生产中的上下文继承不是一回事。在测试环境中,将RootApplicationContextServletApplicationContext作为测试应用程序上下文的一部分。在生产中使用继承而不是简单的包含,正如您在问题中所描述的那样。

似乎来自父上下文的BeanFactoryPostProcessor (在您的情况下是@EnableAspectJAutoProxy )不应用于子上下文。要使它在生产中工作,还必须在子上下文中显式地定义@EnableAspectJAutoProxy

在本例中,Spring上下文定义应该作为下面的代码:

代码语言:javascript
复制
@Configuration
@Import(AopConfig.class)
public class RootApplicationContext {
    ...
}
代码语言:javascript
复制
@Configuration
@Import(AopConfig.class)
public class ServletApplicationContext {
    ...
}

代码语言:javascript
复制
@Configuration
@ComponentScan(basePackageClasses={AopConfig.Class, ...})
public class RootApplicationContext {
    ...
}
代码语言:javascript
复制
@Configuration
@ComponentScan(basePackageClasses={AopConfig.Class, ...})
public class ServletApplicationContext {
    ...
}

相关任务

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39694633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档