Spring:为什么我的容器初始化两次?

时间:2013-12-03 21:55:34

标签: java spring spring-mvc jetty c3p0

看起来我的Spring容器已初始化两次。这不好!我发现这一点的方式是从C3P0连接池获取连接。我在Spring上下文中有一个C3P0 ComboPooledDataSource。

@Bean
@Named("comboPooledDataSource")
public ComboPooledDataSource comboPooledDataSource() {

    Properties properties = properties();

    String environment = getEnvironment();

    ComboPooledDataSource pool = new ComboPooledDataSource();
    try {
        pool.setDriverClass(properties.getProperty("com.pledgeling.platform.db.driver"));
    } catch (PropertyVetoException e) {
        e.printStackTrace();
    }
    pool.setJdbcUrl(properties.getProperty("com.company.db.dsn." + environment));
    pool.setUser(properties.getProperty("com.company.db.user." + environment));
    pool.setPassword(properties.getProperty("com.company.db.pass." + environment));
    pool.setMaxIdleTimeExcessConnections(30 * 60);
    pool.setMaxIdleTime(3 * 60 * 60);

    try {
        Connection testConnection = null;
        testConnection = pool.getConnection();
        System.out.println("Initialized Data Source " + testConnection.toString());
        testConnection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return pool;
}

当容器初始化时,它可以正常工作:

Dec 03, 2013 4:43:49 PM com.mchange.v2.log.MLog <clinit>
INFO: MLog clients using java 1.4+ standard logging.
Dec 03, 2013 4:43:49 PM com.mchange.v2.c3p0.C3P0Registry banner
INFO: Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
Dec 03, 2013 4:43:50 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> z8kflt8y1fq2h6a1npdfoy|7dd8fdd6, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.postgresql.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kflt8y1fq2h6a1npdfoy|7dd8fdd6, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> ..., maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 10800, maxIdleTimeExcessConnections -> 1800, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
Initialized Data Source com.mchange.v2.c3p0.impl.NewProxyConnection@2df8e5e4
Dec 03, 2013 4:43:50 PM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization completed in 5795 ms

但是,我第一次通过webapp访问数据库时,再次建立连接,我不知道为什么。以下是在我的DAO类中抓取连接池的代码

private static ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

private static Connection getConnection() {
    ComboPooledDataSource comboPooledDataSource = (ComboPooledDataSource)context.getBean("comboPooledDataSource");
    try {
        return comboPooledDataSource.getConnection();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

当它被击中时,整个容器似乎再次初始化:

Dec 03, 2013 4:46:28 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
Dec 03, 2013 4:46:28 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@db03ddc: startup date [Tue Dec 03 16:46:28 EST 2013]; root of context hierarchy
Dec 03, 2013 4:46:28 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
Dec 03, 2013 4:46:29 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Dec 03, 2013 4:46:29 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4c84f510: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,config,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,properties,jaxRsServer,comboPooledDataSource,cxf,jaxRsApiApplication,jsonProvider,serverHealthCheck,applicationHealthCheck]; root of factory hierarchy
Dec 03, 2013 4:46:30 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> z8kflt8y1fq2h6a1npdfoy|e9fd18b, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.postgresql.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kflt8y1fq2h6a1npdfoy|e9fd18b, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> ... , maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 10800, maxIdleTimeExcessConnections -> 1800, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
Initialized Data Source com.mchange.v2.c3p0.impl.NewProxyConnection@636ab40a

请注意:我已经使用@Inject或@Autowired语法取得了成功,所以如果这部分解决方案请告诉我在哪里以及如何使用它们。还有一点需要注意:这是一个嵌入式码头9弹簧3零XML uberjar。所有注释都被驱动。

Spring容器在Jetty启动时初始化一次,但我不知道它为什么第二次初始化。

public class JettyStarter {

    public static void main(final String[] args) throws Exception {

        Server server = new Server(8080);
        final ServletHolder servletHolder = new ServletHolder(new CXFServlet());
        final ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");
        context.addServlet(servletHolder, "/application/*");
        context.addEventListener(new ContextLoaderListener());
        context.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
        context.setInitParameter("contextConfigLocation", Config.class.getName());
        server.setHandler(context);
        server.start();
        server.join();
    }
}

1 个答案:

答案 0 :(得分:1)

已注册的ContextLoaderListener

context.addEventListener(new ContextLoaderListener());

将使用指定的AnnotationConfigWebApplicationContext

初始化@Configuration实例
context.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
context.setInitParameter("contextConfigLocation", Config.class.getName());

这将加载一次上下文。

您还在这里加载上下文的第二个副本

private static ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

当加载并初始化包含此成员的类时,会发生这种情况。