实例化实现现有接口的动态加载类

时间:2015-09-09 11:22:36

标签: java classloader urlclassloader

我已经看到了几个类似问题的答案,但不幸的是没有人能够回答我的问题。
我有一个提供计算平台的Web应用程序,为了扩展它,我编写了一个接口,以便应用程序检查特定文件夹中是否有新添加的jar文件,以加载在运行时实现接口的类。
我面临的问题是,即使类加载成功,也无法将新创建的对象强制转换为现有接口“ClassCastException”

   override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "idSecondTV" {            
        let detailViewController = segue.destinationViewController as! mySecondViewController
        detailViewController.findStuff(parameter)
        ...

策略当然是接口实现代码(上面)并返回生成的Strategy对象,所以我宁愿不使用反射来调用加载类中包含的方法,我理解这将是LAO最终得到的同样的问题,因为该方法的参数也被认为是不兼容的。
根据我的阅读,类加载器会考虑现有接口和沿着类加载的接口,将其实现为两种不同的类型,因此是异常。
有没有工作?

3 个答案:

答案 0 :(得分:1)

我知道回答你自己的问题有点奇怪,但是如果有人遇到同样的问题,我还是会这样做。

这就是我一步一步做的。

  • 创建一个包含我的界面的Jar文件以及它所需的模型类。
  • 然后我将jar文件安装到我的本地存储库中,因为我使用maven进行依赖关系管理,因此不需要执行此步骤。
  • 接下来,我在一个单独的项目中创建了我的接口实现,其中我使用上述Jar文件作为依赖项。
  • 然后我在应用程序文件夹中添加了附加策略的Jar文件,该路径用于类加载。
  • 然后我将我的代码更改为:

    ClassLoader sysClassLoader = Strategie.class.getClassLoader();
    URL directory = new URL("file:" + path + "Strategies/Classes/" + strategie + ".jar");
    ClassLoader custom = new URLClassLoader(new URL[] {directory}, sysClassLoader);
    
    Class strategieClass = custom.loadClass(className);
    Object strategieObject = strategieClass.newInstance();
    Strategie strategieInstance= (Strategie) strategieObject;
    

更改类加载器可以避免获得classDef not found Exception。

答案 1 :(得分:0)

ClassCastException建议找到具有该名称的(任何)类(非null)。

也许来自(动态加载二进制类)来自不同编译的托管(调用)源的编译?如果存在这种情况,则类具有相同的名称,但它是DIFFERENT类。

或者也许加载器(主要和动态)预加载了不同的源(jar,classpath等)我不确定这部分答案

来自现实生活的样本:在同一框架的不同版本上开发的两个webapp(在Tomcat / jeety上)可能与具有相同名称的类冲突,但是独立(如果容器不提供加载器分离)

答案 2 :(得分:0)

尝试以下代码。问题是您的jar应该通过CustomClassLoader而不是默认的系统类加载器加载。

// 在初始化期间initializeStrategy()

等某种方法中
            CustomClassLoader customLoader =
                    new CustomClassLoader(getClass().getClassLoader(), new String[] {
                    <CLASSPATH_OF_IMPLEMENTOR_JAR>}
            try {
               specification = (SomeInterface) (customLoader.loadClass(<Implementor>).
                                newInstance());

            } catch (Exception ce) {
                ce.printStackTrace();
            }

// 上传新jar 后,通过(JSP或servlet)触发事件。在某些方法中添加此代码块,例如reloadNewStrategy();

try {
           if (specification; != null) {
                specification;.unload();
            }
            CustomClassLoader customLoader =
                    new CustomClassLoader(getClass().getClassLoader(), new String[] {
                    <CLASSPATH_OF_IMPLEMENTOR_JAR>});
            specification =
                    (SomeInterface) (customLoader.loadClass(<Implementor>).newInstance());
        } catch (Exception err) {
            err.printStackTrace();
        }
}

此处的规范是您的战略界面 实现者是战略实施对象。