我們在我們的一箇舊應用程序中有類似的需求。我們提出的解決方案是一個ResourceManager,它將通過(上下文)ClassLoader檢索資源(記錄器,配置文件等)。
通常,作爲EAR部署的每個應用程序都會獲得自己的ClassLoader,然後該庫可以調用ResourceManager.getLogger()以獲取與當前線程/應用程序關聯的Logger。這樣你就不需要通過庫中的每個方法調用來傳遞它(它需要你可以改變庫的壽命)。
import java.util.*;
import java.util.logging.*;
public class ResourceManager
{
private static final Map<ClassLoader, Map<String, Object>> resources =
Collections.synchronizedMap(new WeakHashMap<ClassLoader, Map<String, Object>>());
public static final String LOGGER = Logger.class.getName();
static
{
// adjust for log4j or other frameworks
final Logger logger = Logger.getLogger("logging.default");
logger.setLevel(Level.ALL);
logger.addHandler(new ConsoleHandler()
{
{
setOutputStream(System.out);
setLevel(Level.ALL);
}
});
registerResource(null, LOGGER, logger);
}
private static ClassLoader getApplicationScope()
{
return Thread.currentThread().getContextClassLoader();
}
public static void registerResource(final String name, final Object resource)
{
registerResource(getApplicationScope(), name, resource);
}
public static synchronized void registerResource(final ClassLoader scope, final String name, final Object resource)
{
Map<String, Object> hm = null;
hm = resources.get(scope);
if (hm == null)
{
hm = Collections.synchronizedMap(new HashMap<String, Object>());
resources.put(scope, hm);
}
hm.put(name, resource);
}
public static Object getResource(final String name)
{
for(ClassLoader scope = getApplicationScope();;scope = scope.getParent())
{
final Map<String, Object> hm = resources.get(scope);
if ((hm != null) && hm.containsKey(name))
{
return hm.get(name);
}
if (scope == null) break;
}
return null;
}
public static void registerLogger(final Logger logger)
{
registerResource(LOGGER, logger);
}
public static Logger getLogger()
{
return (Logger)getResource(LOGGER);
}
}
註冊記錄器在EJB/Web應用程序的初始化階段(需要的任何呼叫到getLogger之前註冊):
Logger logger = Logger.getLogger([Application Logger Name]);
ResourceManager.registerLogger(logger);
檢索記錄器在庫(實用方法):
private Logger getLogger()
{
return ResourceManager.getLogger();
}
這將返回與當前線程關聯的應用程序(EAR)的記錄器。
不限於記錄儀,它也適用於您想要共享的其他資源。
限制:
作爲一個便箋,這個解決方案也可以用來共享各種資源,而不僅僅是記錄器。 – Stefan
你可能想在你的答案中粘貼相關的代碼段,以防鏈接將來死亡。 – rouble
另一個需要注意的方法是在實例化庫之前必須調用ResourceManager.registerLogger()。否則,班級記錄器將全部使用默認記錄器進行設置。對於某些實現來說,這可能是一個破壞行爲。 – rouble