【问题标题】:Is there a Tomcat-like classloader that can be used standalone?是否有可以独立使用的类似 Tomcat 的类加载器?
【发布时间】:2011-11-30 12:51:54
【问题描述】:

我正在使用一个 Java 应用程序服务器 (Smartfox),它可以运行多个应用程序(“扩展”),但是有一个非常不方便的类路径设置来配合它,以及尝试使用时的问题SLF4J。

为了解决这个问题,我想将我的应用程序包装在它们自己的类加载器中。这样一个包含类加载器应该很像 Tomcat 的,因为它

  • 可以从包含 JAR 的目录中加载类。
  • 更喜欢来自自己的类路径的类而不是来自父类的类

是否有某个库具有这样的类加载器,我可以在我的项目中“拖放”?如果没有,自己创建会不会很困难?有什么已知的陷阱吗?

【问题讨论】:

    标签: java classpath osgi classloader encapsulation


    【解决方案1】:

    OSGi(和其他模块系统)旨在完全处理此类问题。

    一开始可能看起来有点矫枉过正,但我​​认为你会很快重新实现 OSGi 已经为你做的事情的重要部分。

    Equinox 是 Eclipse 使用的 OSGi 实现,例如。

    【讨论】:

    • 这似乎是我想要的,但是虽然有关创建捆绑包的教程很多,但我很难找到有关如何在其中嵌入 OSGI 框架/容器(使用 Equinox 或 Felix)的信息我的应用程序。有任何相关信息吗?
    • @BartvanHeukelom:您通常不会将 OSGi 嵌入到您的应用程序中,而是反过来:您将应用程序(和插件)创建为 OSGi 包。
    • 我知道,但我的应用程序本身就是 Smartfox 中的插件/扩展,我无法将 Smartfox 放入 OSGi。无论如何,我在felix.apache.org/site/… 找到了一些东西
    • 有关扩展设置的详细信息,请参阅smartfoxserver.com/docs/docPages/sfsPro/javaExtensions.htm
    • 我写了一篇关于如何在应用程序中嵌入 OSGi 的博文。对于最简单的情况,只需大约 5 行代码:njbartlett.name/2011/03/07/embedding-osgi.html
    【解决方案2】:

    由于我在嵌入 OSGi 容器时遇到了麻烦,而且确实有点矫枉过正,所以我推出了自己的解决方案。但有一天我会在不需要嵌入框架的情况下学会使用 OSGi。

    如果您以某种方式碰巧想要使用此代码,则它属于“随心所欲地使用它”许可。

    public class SmartfoxExtensionContainer extends AbstractExtension {
    
        private AbstractExtension extension;
    
        private void initRealExtension() {
            final String zone = this.getOwnerZone();
            System.out.println("[SmartfoxExtensionContainer] ========= Init extension for zone " + zone + " =========");
    
            try {
    
                // load properties
                File propFile = new File("wext/" + zone + ".properties");
                System.out.println("[SmartfoxExtensionContainer] Load config from " + propFile.getCanonicalPath());
                Properties props = new Properties();
                final FileInputStream ins = new FileInputStream(propFile);
                try {
                    props.load(new InputStreamReader(ins, "UTF-8"));
                } finally {
                    try {
                        ins.close();
                    } catch (IOException e) {}
                }
    
                // construct classloader
                File jarDir = new File(props.getProperty("classpath", "wext/" + zone));
                System.out.println("[SmartfoxExtensionContainer] Load classes from " + jarDir.getCanonicalPath());
                if (!jarDir.isDirectory()) throw new RuntimeException("That is not an existing directory");
    
                final File[] fs = jarDir.listFiles();
    
                URL[] urls = new URL[fs.length];
    
                for (int f = 0; f < fs.length; f++) {
                    System.out.println("[SmartfoxExtensionContainer]     " + fs[f].getName());
                    urls[f] = fs[f].toURI().toURL();
                }
    
                SelfishClassLoader cl = new SelfishClassLoader(urls, SmartfoxExtensionContainer.class.getClassLoader());
    
                // get real extension class
                String mainClass = props.getProperty("mainClass", "Extension");
                System.out.println("[SmartfoxExtensionContainer] Main class: " + mainClass);
    
                @SuppressWarnings("unchecked")
                Class<? extends AbstractExtension> extClass = (Class<? extends AbstractExtension>) cl.loadClass(mainClass);
    
                // create extension and copy settings
                extension = extClass.newInstance();
                extension.setOwner(this.getOwnerZone(), this.getOwnerRoom());
    
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /* ======================= DELEGATES ======================= */
    
        @Override
        public void init() {
            initRealExtension();
            extension.init();
        }
    
        @Override
        public void destroy() {
            extension.destroy();
        }
    
        @Override
    public void handleRequest(String arg0, ActionscriptObject arg1, User arg2, int arg3) {
        extension.handleRequest(arg0, arg1, arg2, arg3);
    }
    
    @Override
    public void handleRequest(String arg0, String[] arg1, User arg2, int arg3) {
        extension.handleRequest(arg0, arg1, arg2, arg3);
    }
    
    @Override
    public void handleInternalEvent(InternalEventObject arg0) {
        extension.handleInternalEvent(arg0);
    }
    
    @Override
    public Object handleInternalRequest(Object params) {
        return extension.handleInternalRequest(params);
    }
    
    @Override
    public void handleRequest(String cmd, JSONObject jso, User u, int fromRoom) {
        extension.handleRequest(cmd, jso, u, fromRoom);
    }
    
        /* ======================= CUSTOM CLASSLOADER ======================= */
    
        private static class SelfishClassLoader extends URLClassLoader {
    
            SelfishClassLoader(URL[] urls, ClassLoader parent) {
                super(urls, parent);
            }
    
            // override default behaviour: find classes in local path first, then parent
            @Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    
                // First, check if the class has already been loaded
                Class<?> clz = findLoadedClass(name);
    
                if (clz == null) {
    
                    try {
                        clz = findClass(name);
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from current class loader
                    }
    
                    if (clz == null) {
                        // If still not found, then invoke parent.findClass in order
                        // to find the class.
                        clz = getParent().loadClass(name);
                    }
    
                }
    
                if (resolve) {
                    resolveClass(clz);
                }
    
                return clz;
    
            };
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-12
      • 2011-08-24
      • 2015-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多