从another question开始,如果将对象添加到在main方法(系统类加载器)期间实例化的上下文属性,但随后在Web App类加载器上下文中使用(即,在servlet中) ,有些问题似乎无法解决:
发生以下两件事之一:
WebAppContext.addSystemClasses(server, SomeClass.class.getName())
,您可以获得java.lang.LinkageError: loader constraint violation: when resolving method...
。这可能是因为我只包括了基础如果没有强制在WebApp中使用SystemClassLoader,那还有办法吗?这是一个可行的解决方案吗?这样做的缺点是什么?
答案 0 :(得分:0)
不要尝试在运行时解析该类。 意思是,如果您只使用Class,它加载的分钟,它固定在当前上下文类加载器的任何位置。请注意这一点。 更好的是,总是在这里使用字符串或包。
使用Binding中的Class直接将Class绑定在错误的System Classloader上。
来自jetty-webapp-logging
的示例(捕获服务器级别的所有日志记录)。
public class CentralizedWebAppLoggingBinding implements AppLifeCycle.Binding
{
public String[] getBindingTargets()
{
return new String[]
{ "deploying" };
}
public void processBinding(Node node, App app) throws Exception
{
ContextHandler handler = app.getContextHandler();
if (handler == null)
{
throw new NullPointerException("No Handler created for App: " + app);
}
if (handler instanceof WebAppContext)
{
WebAppContext webapp = (WebAppContext)handler;
// Older API
webapp.addSystemClass("org.apache.log4j.");
webapp.addSystemClass("org.slf4j.");
webapp.addSystemClass("org.apache.commons.logging.");
}
}
}
您也可以从WebApp的角度访问Class,这样可以确保您的ClasspathPattern也是理智的。
package jetty.deploy;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppLifeCycle;
import org.eclipse.jetty.deploy.graph.Node;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.thread.ThreadClassLoaderScope;
import org.eclipse.jetty.webapp.ClasspathPattern;
import org.eclipse.jetty.webapp.WebAppContext;
public class ExampleClassLoaderBinding implements AppLifeCycle.Binding
{
@Override
public String[] getBindingTargets()
{
return new String[]{AppLifeCycle.DEPLOYING};
}
@Override
public void processBinding(Node node, App app) throws Exception
{
ContextHandler handler = app.getContextHandler();
if (handler == null)
{
throw new NullPointerException("No Handler created for App: " + app);
}
if (handler instanceof WebAppContext)
{
WebAppContext webapp = (WebAppContext) handler;
try (ThreadClassLoaderScope scope = new ThreadClassLoaderScope(webapp.getClassLoader()))
{
// Demonstration of newer API
ClasspathPattern systemClasspathPattern = webapp.getSystemClasspathPattern();
systemClasspathPattern.add("org.apache.log4j.");
systemClasspathPattern.add("org.slf4j.");
systemClasspathPattern.add("org.apache.commons.logging.");
// Example of accessing class via WebApp scope
Class<?> clazz = Class.forName("com.corp.MyClass", true, scope.getScopedClassLoader());
Object obj = clazz.getDeclaredConstructor().newInstance();
}
}
}
}