All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dexcoder.commons.bean.ContextClassLoaderLocal Maven / Gradle / Ivy

The newest version!
package com.dexcoder.commons.bean;

import java.util.Map;
import java.util.WeakHashMap;

/**
 * 该类的一个实例表示为线程的ContextClassLoader提供一个值。
 * 
* 有时需要将值存储在全局变量“global”,(包括使用的单例模式) *
* 在只有一个classloader的应用程序,数据可以简单的存储在一些类的“static”成员。 * 当涉及多个classloader,该方法可能会失败。 * 尤其是,这些不工作的代码可能会运行在一个servlet容器或j2ee容器, * 通过“共享”的classloader加载的类的静态成员变量,在容器内运行的所有组件都是可见的。 * 这个类提供了一个ClassLoader实例数据关联机制,确保代码在这样的容器运行时每个组件都有自己的副本在“全局”的变量而不是意外的提供一个副本, * 当变量和其它组件碰巧同一时间运行在同一容器(比如:servlets 或 EJBs)。 * * 这个类是java.lang.ThreadLocal 的加强模式,允许与特定线程相关联的数据执行类型的任务。 * * 当使用这个类的代码作为“一般”应用程序运行,即不在容器内,与只使用一个静态成员变量来存储数据的效果是相同的 * 因为Thread.getContextClassLoader总是返回相同的classloader(系统的classloader)。 * *

期望的使用方法如下:
*

 *  public class SomeClass {
 *    private static final ContextClassLoaderLocal global
 *      = new ContextClassLoaderLocal() {
 *          protected Object initialValue() {
 *              return new String("Initial value");
 *          };
 *
 *    public void testGlobal() {
 *      String s = (String) global.get();
 *      System.out.println("global value:" + s);
 *      buf.set("New Value");
 *    }
 * 
*

* *

* 注意: * 这个类需要小心一些,确保使用这个类的组件由容器来“取消部署”, * 特定的组件classloader和所有相关联的类(和他们的表态变量)进行垃圾回收。 * * 不幸的是有一个场景这个类不会正常工作,更不幸的是没有已知的解决方法: * 当组件被取消部署,组件(或容器)调用该类实例的“unset”方法 * * 该问题发生于: *

    *
  • 通过一个共享的classloader加载的这个类包含静态的实例
  • *
  • 实例中存储的值是一个通过特定组件的classloader加载的对象(或任何对象,它指的是通过那个classloader加载)。
  • *
* 其结果是,该map管理的这个对象,仍包含所存储对象的强引用,它是由包含一个强引用的classloader加载的, * 这意味着容器“取消部署”,组件、特定组件的classloader和所有相关的类和静态变量不能被垃圾回收。 * * 如果容器需要每个组件加载所有的设置和类,需要避免通过“共享的”classloader来提供类加载。 * *

* User: liyd * Date: 13-5-9 下午4:10 * version $Id: ContextClassLoaderLocal.java, v 0.1 Exp $ */ public class ContextClassLoaderLocal { /** 保存实际实例的数据信息 */ private Map valueByClassLoader = new WeakHashMap(); /** 全局初始值初始化标记 */ private boolean globalValueInitialized = false; /** 全局初始值 */ private Object globalValue; /** * 构造方法 */ public ContextClassLoaderLocal() { super(); } /** * 返回这个 ContextClassLoaderLocal 的初始值变量 * 每一次调用该方法的为每一个 ContextClassLoaderLocal 的 ContextClassLoader * 首次访问为get或set。 * 如果程序员希望 ContextClassLoaderLocal 变量被初始化为null以外的一些值, * ContextClassLoaderLocal 必须被继承并且该方法被重写。 * 通常情况下,使用一个匿名的内部类。 * initialValue 的典型实现是调用一个适当的构造函数,并且返回新构造的对象。 * * @return 该ContextClassLoaderLocal的一个初始值,用来作为使用的新的对象 */ protected Object initialValue() { return null; } /** * 获取实例 * 这是一个伪单例。 * 这是一个伪单例 - 每一个线程的ContextClassLoader提供一个单例的实例 * 这种机制提供了在同一个web容器中部署的应用程序之间的隔离 * * @return 当前线程ContextClassLoader的关联对象 */ public synchronized Object get() { // 同步整个方法会有点慢, // 但是保证不会有微秒的线程问题,并且不需要同步 valueByClassLoader // make sure that the map is given a change to purge itself // valueByClassLoader.isEmpty(); try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) { Object value = valueByClassLoader.get(contextClassLoader); if ((value == null) && !valueByClassLoader.containsKey(contextClassLoader)) { value = initialValue(); valueByClassLoader.put(contextClassLoader, value); } return value; } } catch (SecurityException e) { } // 出现异常,返回全局变量值 if (!globalValueInitialized) { globalValue = initialValue(); globalValueInitialized = true; } return globalValue; } /** * 设置值 - 一个值提供一个线程的 ContextClassLoader * 这种机制提供了在同一个web容器中部署的应用程序之间的隔离 * * @param value 新的线程ContextClassLoader关联的对象 */ public synchronized void set(Object value) { // 同步整个方法会有点慢, // 但是保证不会有微秒的线程问题,并且不需要同步 valueByClassLoader // // make sure that the map is given a change to purge itself // valueByClassLoader.isEmpty(); try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) { valueByClassLoader.put(contextClassLoader, value); return; } } catch (SecurityException e) { } //如有异常,设置全局值 globalValue = value; globalValueInitialized = true; } /** * 卸载当前线程ContextClassLoader关联的对象 */ public synchronized void unset() { try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); unset(contextClassLoader); } catch (SecurityException e) { /* SWALLOW - should we log this? */ } } /** * 卸载当前线程ContextClassLoader关联的对象 * * @param classLoader 需要卸载的ClassLoader */ public synchronized void unset(ClassLoader classLoader) { valueByClassLoader.remove(classLoader); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy