为什么要将spring bean初始化两次

时间:2015-04-20 09:48:43

标签: java spring spring-mvc applicationcontext

Spring(mvc)4.0.3,java 1.7.0_71,tomcat 7.0.57,windows 7

我有一个Spring MVC应用程序,有2个applicationContexts,applicationContextRoot加载了:

AbstractAnnotationConfigDispatcherServletInitializer: protected Class<?>[]  getRootConfigClasses {
    return new Class<?>[] { AppConfig.class }
}

WebApplicationContext加载了。

protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[] {WebMvcConfig.class};
}

AppConfig类包含焦点Bean的bean定义(Dropwizard的MetricRegistry

@Configuration
public class AppConfig {
    ...
    @Bean
    public MetricRegistry metricRegistry() {
        MetricRegistry result = new MetricRegistry();
        LOG.info("testing", new Exception("trace me"));
        configureReporters(result);
        return result;
}

我看到trace me stacktrace被叫了两次。堆栈跟踪是不同的:

....zipped
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) [spring-context-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) [spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) [spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) [spring-web-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4992) [catalina.jar:7.0.57]
> at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5492) [catalina.jar:7.0.57]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.57]

对比(后来很少有人)。

at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) [spring-context-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658) [spring-webmvc-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530) [spring-webmvc-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484) [spring-webmvc-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136) [spring-webmvc-4.0.3.RELEASE.jar:4.0.3.RELEASE]
> at javax.servlet.GenericServlet.init(GenericServlet.java:158) [servlet-api.jar:3.0.FR]
> at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284) [catalina.jar:7.0.57]
> at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1090) [catalina.jar:7.0.57]
> at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5231) [catalina.jar:7.0.57]
> at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5518) [catalina.jar:7.0.57]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.57]

第一次在web.context.ContextLoader上下文中创建bean,而第二次在web.servlet.FrameworkServlet中创建它 除了安全性约束之外,web.xml是空的,初始化是通过AbstractAnnotationConfigDispatcherServletInitializer

的实例完成的

我不确定这种行为的影响,但它不是我所期望的(bean是单身等)。如果我向这个bean取出每个@autowired注释,这种行为仍然存在。我确实检查过只有一个@componentscan(在WebMvcConfig中)

1 个答案:

答案 0 :(得分:3)

听起来好像是WebMvcConfig中的组件扫描,但不包括配置类。

你可以这样做:

@ComponentScan(
    basePackages = {"mypackage"}, 
    excludeFilters = 
        @ComponentScan.Filter(
            type = FilterType.ANNOTATION, 
            value = Configuration.class
        )
)