Eski uygulamalarımızdan birinde benzer bir ihtiyacımız vardı. Geldiğimiz çözüm, (içerik) ClassLoader tarafından kaynakları (Logger, Config dosyaları vb.) Alabilecek bir ResourceManager'tı.
Genellikle EAR tarafından dağıtılan her uygulama kendi ClassLoader'ını alır ve kitaplık o anda geçerli Thread/Application ile ilişkili Logger'ı almak için ResourceManager.getLogger() öğesini çağırır. Bu şekilde kütüphanede her yöntem çağrısıyla iletmenize gerek yoktur (kütüphaneyi değiştirmenizi gerektirir).
Logger logger = Logger.getLogger([Application Logger Name]);
ResourceManager.registerLogger(logger);
kütüphanede Kaydediciyi al (yardımcı yöntemi):
private Logger getLogger()
{
return ResourceManager.getLogger();
}
EJB/WebApp init fazında
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);
}
}
Kayıt Kaydedici (getLogger için herhangi bir çağrı önce kayıtlı olması gerekir)
Bu, geçerli iş parçacığıyla ilişkili uygulama için kaydediciyi (EAR) döndürecektir.
Logger'larla sınırlı değil, paylaşmak istediğiniz diğer kaynaklar için de çalışıyor.
Sınırlamalar: Eğer dağıtılan EAR
ResourceManager ve Günlük kütüphaneye başına birden fazla uygulama/EJB'ler paket halinde
alışkanlık iş aynı veya kütüphane ve uygulama daha yüksek ClassLoader üzerinde olması gerekiyor. Paketleme seçeneği varsa, Alexanders yaklaşımı daha temizdir. (varsayılan olarak sunucu seviyesinde olan java.util.logging'i kullanır, böylece yaklaşımı işe yaramaz)
Bir yan not olarak, bu çözüm, sadece kaydedicilere değil, her türlü kaynağı paylaşmak için de kullanılabilir. – Stefan
linkin gelecekte ölmesi durumunda, cevabınıza ilgili kod bölümlerini yapıştırmak isteyebilirsiniz. – rouble
Bu yöntem hakkında dikkat edilmesi gereken diğer bir nokta, kitaplığın başlatılmasından önce ResourceManager.registerLogger() öğesinin çağrılması gerektiğidir. Aksi takdirde, sınıf kaydedicileri varsayılan kayıt cihazı kullanılarak ayarlanacaktır. Bu, bazı uygulamalar için bir anlaşma olabilir. – rouble