0 0

关于java static变量初始化的疑问10

java中,类的static变量作为类变量,只需要被一次初始化,就可使用,但是,我在程序中遇到一个问题:

在web.xml中配置listener,服务器启动时,ServletContextListen初始化数据源(DataSource),第一次初始化成功,但是在Test类中,调用ConnectionManager.getConnection()时,DataSource却为null,意味着ServletContextListen初始化数据源失败了,大家帮忙解答下,到底什么原因造成的,谢谢!!!

以下是代码:
package c3p0.connection;

import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class ConnectionManager {
	private static DataSource data_source=null;;
	private static Properties props=null;
	private static String porps_name=null;
	
	/**
	 * 创建数据库连接池
	 * @return
	 */
	private static DataSource createDataSource(){
		load();
		data_source=initDB();
		return data_source;
	}
		
	/**
	 * 加载配置文件
	 */
	private static void load(){
		try {
			props =  new Properties();
			InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream(porps_name);
			props.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 初始化数据库
	 */
	private static  DataSource initDB(){
		System.out.println("开始初始化数据源...");
		ComboPooledDataSource pool_ds=new ComboPooledDataSource();
		try {
			pool_ds.setDriverClass(getProperty("c3p0.connection.driverClass"));
		} catch (PropertyVetoException e) {
			e.printStackTrace();
			throw new RuntimeException("数据库驱动加载失败");
		}
		pool_ds.setJdbcUrl(getProperty("c3p0.connection.url"));
		pool_ds.setUser(getProperty("c3p0.connection.user"));
		pool_ds.setPassword(getProperty("c3p0.connection.password"));
		pool_ds.setInitialPoolSize(Integer.parseInt(getProperty("c3p0.connection.initialPoolSize")));
		pool_ds.setMaxPoolSize(Integer.parseInt(getProperty("c3p0.connection.maxPoolSize")));
		pool_ds.setMinPoolSize(Integer.parseInt(getProperty("c3p0.connection.minPoolSize")));
		pool_ds.setMaxIdleTime(Integer.parseInt(getProperty("c3p0.connection.maxIdleTime")));
		pool_ds.setAcquireIncrement(Integer.parseInt(getProperty("c3p0.connection.acquireIncrement")));
		pool_ds.setAcquireRetryAttempts(Integer.parseInt(getProperty("c3p0.connection.acquireRetryAttempts")));
		pool_ds.setAcquireRetryDelay(Integer.parseInt(getProperty("c3p0.connection.acquireRetryDelay")));
		pool_ds.setTestConnectionOnCheckout(Boolean.parseBoolean(getProperty("c3p0.connection.testConnectionOnCheckout")));
		pool_ds.setTestConnectionOnCheckin(Boolean.parseBoolean(getProperty("c3p0.connection.testConnectionOnCheckin")));
		pool_ds.setIdleConnectionTestPeriod(Integer.parseInt(getProperty("c3p0.connection.idleConnectionTestPeriod")));
		pool_ds.setCheckoutTimeout(Integer.parseInt(getProperty("c3p0.connection.checkoutTimeout")));
		pool_ds.setAutomaticTestTable(getProperty("c3p0.connection.automaticTestTable"));
		
		System.out.println("数据源初始化完毕...");
		return pool_ds;
	}
	
	/**
	 * 获取c3p0连接池文件配置信息
	 * @param key
	 * @return
	 */
	private static String getProperty(String key){
		if(key==null||"".equals(key)){
			throw new NullPointerException("key不能为空!!!请检查key的赋值!!!");
		}
		return props.getProperty(key);
	}
	
	public static Connection getConnection() throws SQLException{
		data_source=(data_source==null) ? createDataSource() : data_source;
		return data_source.getConnection();
	}
	
	public static void start(String porps_name) throws SQLException{
		ConnectionManager.porps_name=porps_name;
		Connection conn=getConnection();
		conn.close();
	}
	
	public static void stop(){
		data_source=null;
	}
	
	public static void release(Connection conn,PreparedStatement pstmt,ResultSet res){
			try {
				if(conn!=null){
					conn.close();
				}
				if(pstmt!=null){
					pstmt.close();
				}
				if(res!=null){
					res.close();
				}
			} catch (SQLException e) {
				
				e.printStackTrace();
			}
		
	}
	
}


package mystruts.listener;

import java.sql.SQLException;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import c3p0.connection.ConnectionManager;

/**
 * ServletContext 上下文监听器
 * 应用服务器一启动就产生该对象,服务器关闭即销毁
 * 作用于全局,所有Servlet ,相当于静态变量
 * @author tianly
 *
 */
public class ServletContextListen implements ServletContextListener {
	/**
	 * web服务器关闭时执行
	 */
	@Override
	public void contextDestroyed(ServletContextEvent event) {
		/**
		 * 关闭数据源
		 */
		ConnectionManager.stop();
	}
	
	
	/**
	 * web服务器启动时执行
	 */
	@Override
	public void contextInitialized(ServletContextEvent event) {
		
		/**
		 * 初始化数据源
		 */
		String db_url=event.getServletContext().getInitParameter("DataBaseConfig");
		try {
			ConnectionManager.start(db_url);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

}


package test.c3p0;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import c3p0.connection.ConnectionManager;
import c3p0.util.DateUtil;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String currdate=DateUtil.getDateTime();
		Connection conn=null;
		PreparedStatement pstmt=null;
		ResultSet res=null;
		try {
			String sql="insert into userinfo(username,password,sex,regdate) values(?,?,?,?)";
			String sql4ID="select LAST_INSERT_ID()";
			conn=ConnectionManager.getConnection();
			conn.setAutoCommit(false);
			pstmt=conn.prepareStatement(sql);
			pstmt.setString(1, "tly");
			pstmt.setString(2, "tly");
			pstmt.setInt(3, 0);
			pstmt.setString(4, currdate);	//mysql中无需进行日期格式转换
			
			pstmt.executeUpdate();
			pstmt=conn.prepareStatement(sql4ID);
			res=pstmt.executeQuery();
			if(res.next()){
				int ID=res.getInt(1);
				System.out.println("ID:"+ID);
			}
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally{
			ConnectionManager.release(conn, pstmt, res);
		}

	}

}


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>mysystem</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
 
  
  <!-- 登录Servlet配置
  <servlet>
  	<servlet-name>LoginServlet</servlet-name>
  	<servlet-class>login.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>LoginServlet</servlet-name>
  	<url-pattern>/login</url-pattern>
  </servlet-mapping> -->
  
  <filter>
  	<filter-name>ActionDispatcher</filter-name>
  	<filter-class> mystruts.actionfilter.ActionDispatcher</filter-class>
  </filter>
  
   <filter-mapping>
  	<filter-name>ActionDispatcher</filter-name>
  	<url-pattern>*.action</url-pattern>
  </filter-mapping>
  
  <!-- 数据库信息配置 -->
  <context-param>
  	<param-name>DataBaseConfig</param-name>
  	<param-value>c3p0/c3p0.properties</param-value>
  </context-param>
  <listener>
  	<listener-class>mystruts.listener.ServletContextListen</listener-class>
  </listener>
  
  
  
  
</web-app>


在Test类中,调用ConnectionManager.getConnection()时,DataSource却为null,但我在debug时,跟踪查看,发现DataSource是被初始化了,不知什么原因造成初始化失败,请大家帮忙查看下,谢谢
2012年9月05日 13:13

7个答案 按时间排序 按投票排序

0 0

采纳的答案

没必要放到ServletContextListener。

直接放在ConnectionManager中的static块中,默认加载classpath下的配置文件。

如 static {
        load(); 
        data_source=initDB(); 
        return data_source; 
    }
读取classpath下的资源可以通过
  Thread.currentThread().getContextClassLoader().getResourceAsStream(name)

    public static void stop(){ 
        data_source=null;   //容器销毁了 自动垃圾回收了,不需要
    }


报的什么异常,能否全部贴出来

2012年9月05日 13:38
0 0

兄弟你太幽默了。。。监听器 是运行在web容器里的。是一个jvm实例。

main方法是另外一个jvm实例。

本质是两个main方法。。能互相调用彼此的运行时变量么。。。

2012年9月06日 11:41
0 0

楼上说得对。

你建一个Servlet,把那段测试代码放到Servlet里去,再用浏览器调Servlet.

2012年9月05日 17:52
0 0

前面的几个哥们也都说了,如果配置在xml中那么你肯定得去启动这个xml才能生效。
如果你想测试你的代码用测试类中mian方法来测试,你首先要去执行xml文件。

2012年9月05日 16:34
0 0

要看你的tomcat启动了没的,如果没有启动,你的test又没连接数据库,如何会拿到值啊。
你的初始化是tomcat启动后才会去初始化的。

2012年9月05日 16:15
0 0

其它的 我就不多说了 ,开源中国  红薯大哥也是用的 c3p0,同时 他把它的数据库 工具类  已经贡献出来了


package my.db;

import java.sql.*;
import java.util.*;
import java.lang.reflect.*;

import javax.sql.DataSource;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 数据库管理
 * @author Winter Lau
 * @date 2010-2-2 下午10:18:50
 */
public class DBManager {

	private final static Log log = LogFactory.getLog(DBManager.class);
	private final static ThreadLocal<Connection> conns = new ThreadLocal<Connection>();
	private static DataSource dataSource;
	private static boolean show_sql = false;
	
	static {
		initDataSource(null);
	}

	/**
	 * 初始化连接池
	 * @param props
	 * @param show_sql
	 */
	private final static void initDataSource(Properties dbProperties) {
		try {
			if(dbProperties == null){
				dbProperties = new Properties();
				dbProperties.load(DBManager.class.getResourceAsStream("db.properties"));
			}
			Properties cp_props = new Properties();
			for(Object key : dbProperties.keySet()) {
				String skey = (String)key;
				if(skey.startsWith("jdbc.")){
					String name = skey.substring(5);
					cp_props.put(name, dbProperties.getProperty(skey));
					if("show_sql".equalsIgnoreCase(name)){
						show_sql = "true".equalsIgnoreCase(dbProperties.getProperty(skey));
					}
				}
			}
			dataSource = (DataSource)Class.forName(cp_props.getProperty("datasource")).newInstance();
			if(dataSource.getClass().getName().indexOf("c3p0")>0){
				//Disable JMX in C3P0
				System.setProperty("com.mchange.v2.c3p0.management.ManagementCoordinator", 
						"com.mchange.v2.c3p0.management.NullManagementCoordinator");
			}
			log.info("Using DataSource : " + dataSource.getClass().getName());
			BeanUtils.populate(dataSource, cp_props);

			Connection conn = getConnection();
			DatabaseMetaData mdm = conn.getMetaData();
			log.info("Connected to " + mdm.getDatabaseProductName() + 
                              " " + mdm.getDatabaseProductVersion());
			closeConnection();
		} catch (Exception e) {
			throw new DBException(e);
		}
	}
	
	/**
	 * 断开连接池
	 */
	public final static void closeDataSource(){
		try {
			dataSource.getClass().getMethod("close").invoke(dataSource);
		} catch (NoSuchMethodException e){ 
		} catch (Exception e) {
			log.error("Unabled to destroy DataSource!!! ", e);
		}
	}

	public final static Connection getConnection() throws SQLException {
		Connection conn = conns.get();
		if(conn ==null || conn.isClosed()){
			conn = dataSource.getConnection();
			conns.set(conn);
		}
		return (show_sql && !Proxy.isProxyClass(conn.getClass()))?
                      new _DebugConnection(conn).getConnection():conn;
	}
	
	/**
	 * 关闭连接
	 */
	public final static void closeConnection() {
		Connection conn = conns.get();
		try {
			if(conn != null && !conn.isClosed()){
				conn.setAutoCommit(true);
				conn.close();
			}
		} catch (SQLException e) {
			log.error("Unabled to close connection!!! ", e);
		}
		conns.set(null);
	}

	/**
	 * 用于跟踪执行的SQL语句
	 * @author Winter Lau
	 */
	static class _DebugConnection implements InvocationHandler {
		
		private final static Log log = LogFactory.getLog(_DebugConnection.class);
		
		private Connection conn = null;

		public _DebugConnection(Connection conn) {
			this.conn = conn;
		}

		/**
		 * Returns the conn.
		 * @return Connection
		 */
		public Connection getConnection() {
			return (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), 
                             conn.getClass().getInterfaces(), this);
		}
		
		public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
			try {
				String method = m.getName();
				if("prepareStatement".equals(method) || "createStatement".equals(method))
					log.info("[SQL] >>> " + args[0]);				
				return m.invoke(conn, args);
			} catch (InvocationTargetException e) {
				throw e.getTargetException();
			}
		}

	}
	
}


http://www.oschina.net/code/snippet_12_8

2012年9月05日 14:09
0 0

那是应为他们没有运行在同一个环境中,,服务器启动是在tomcat容器中的,而你自己写的test类 是在外面JDK里面跑的 和 tomcat没有关系,当然是空了

2012年9月05日 13:29

相关推荐

    Java中static静态变量的初始化完全解析

    ### 静态变量初始化的基本规则: 1. **默认初始化**:当类被加载时,静态变量首先会被赋予其数据类型的默认值。例如,`int`类型的静态变量会被初始化为`0`,`boolean`为`false`,引用类型为`null`。 2. **显式初始化...

    Java static静态初始快

    在Java编程语言中,`static`关键字扮演着重要的角色,特别是在初始化类的静态成员时。`static`静态初始化块是用来初始化类级别的变量,也就是说,这些变量是属于类本身,而不是类的实例。当我们讨论“Java static...

    Java静态初始化块和对象初始化块

    静态初始化块是以`static`关键字标识的代码块,它在类被加载到Java虚拟机(JVM)时执行,且只执行一次。静态初始化块常用于设置类级别的变量,或者执行只应执行一次的初始化操作。例如,如果一个类需要在程序运行前...

    java数组初始化详解

    需要注意的是,在 Java 中,数组变量必须在使用前进行初始化,否则将会抛出 NullPointerException。 二维数组的初始化 在 Java 中,二维数组可以通过多种方式进行初始化。 1. 声明数组变量:`int[][] a;`,这只...

    探究java的ClassLoader及类变量初始化顺序

    理解ClassLoader的工作机制以及类变量初始化的顺序对于深入理解Java运行时环境至关重要。这篇博文将探讨这两个主题。 首先,让我们深入了解Java的ClassLoader。ClassLoader是一个抽象类,它是Java中的一个关键组件...

    java中的static变量,方法,代码块

    Static变量 `static`变量,亦称为静态变量或类变量,与实例变量相对。其最显著的特点在于,无论创建多少个该类的实例,`static`变量在内存中仅存在一份拷贝,这意味着所有实例共享同一份变量值。这不仅节约了内存...

    java中类的初始化顺序

    // 实例成员变量初始化 public static TestB b = new TestB(); public static void main(String[] args) { new TestOrder(); } } class TestA { public TestA() { System.out.println("Test--A"); } } ...

    学习java静态数据初始化.doc

    在 Java 中,静态数据初始化是指在类加载过程中对静态变量的初始化。静态变量是在类加载时被初始化的,而不是在实例创建时。静态变量的初始化顺序是按照它们在类中的定义顺序进行的。 在 Java 中有两种类型的变量:...

    Java static修饰成员变量

    综上所述,`static`关键字在Java中具有多种用途,包括定义类变量、类方法、静态初始化块以及静态内部类。理解和正确使用`static`对于编写高效、可维护的Java代码至关重要。在实际编程中,要根据需求选择是否使用`...

    java程序初始化顺序

    - 静态初始化块(static{}):如果类中存在静态初始化块,该块的代码会在类加载后的准备阶段执行,用于初始化静态变量或执行其他静态设置任务。 - 静态变量的赋值:接着,静态变量会被赋予它们的初始值,这可以是...

    Java初始化顺序1

    在 Java 中,实例变量的初始化顺序是按照定义的顺序进行的,而静态变量的初始化顺序则是按照定义的顺序,并且只在第一次访问时初始化。 在上面的示例代码中,我们可以看到,类变量和实例变量的初始化顺序是按照定义...

    6种方法初始化JAVA中的list集合

    本文将详细介绍6种初始化Java List集合的方法,并通过代码示例帮助理解每种方法的使用和特点。 1. 常规方式 这是最常见的初始化List的方式,通过创建ArrayList实例并逐个添加元素。自JDK 7以后,可以省略泛型类型的...

    Java静态和非静态成员变量初始化过程解析

    Java静态和非静态成员变量初始化过程解析 Java静态和非静态成员变量初始化过程解析是Java语言中一个非常重要的概念。了解Java静态和非静态成员变量的初始化过程对大家的学习或者工作具有一定的参考学习价值。 首先...

    java面试题-类的初始化顺序.doc

    这个顺序表明,无论类之间的继承关系如何,初始化顺序始终是:静态变量和静态初始化块先于非静态成员。在创建对象时,父类的初始化先于子类。这是Java语言规范所规定的,确保在子类访问父类的静态或非静态成员时,...

    Java类变量和成员变量初始化过程的应用介绍

    2. **对象的生成及成员变量初始化**: 当创建一个新对象时,成员变量的初始化过程分为两个阶段: - 首先,执行实例初始化块(如果存在)。实例初始化块中的代码会在每次创建新对象时运行,且在构造函数调用之前。 ...

    php 静态变量的初始化

    然而,如果你想要将静态变量初始化为一个对象,PHP并不支持像Java那样的静态构造器或静态初始化块。在这种情况下,你需要在代码的某个时刻显式地调用一个方法来完成初始化。例如: ```php class A { static ...

    Java初始化块Java初始化块.doc

    Java 初始化块,也称为构造代码块,是Java编程语言中的一种特性,用于在对象创建时执行特定的初始化操作。初始化块在类的定义中以 `{}` 包裹的一段代码,没有返回值,也不需要任何参数。根据是否带有 `static` ...

    深入java虚拟机加载初始化

    ### 深入Java虚拟机加载初始化 #### Classloader的作用及意义 在深入了解Java虚拟机(JVM)的加载初始化之前,我们先明确一下`Classloader`的角色。简单地说,`Classloader`的主要职责是将编译后的`.class`文件...

    深入java虚拟机(三)——类的生命周期(下)类的初始化1

    类的静态变量初始化是有序的,遵循类文件中的顺序,从上到下依次初始化。这一点在面试中可能会被问及,例如在给定的代码片段中: ```java public class Test { public static int a = 0; public static int b ; ...

    java中如何使用Static的变量和方法.doc

    #### Static变量的特点 1. **共享性**:当声明了一个`static`变量后,这个变量由所有该类的实例共享,而不是每个实例拥有单独的副本。 2. **生命周期**:`static`变量的生命周期与类相同,即当类加载到内存中时,`...

Global site tag (gtag.js) - Google Analytics