【问题标题】:Create object from class name without reflection从类名创建对象而不用反射
【发布时间】:2023-02-14 23:20:31
【问题描述】:

我有一个主应用程序,它使用一个外部 jar 和一些我想从我的主应用程序调用的插件。在我的主应用程序中,我有一个外部 jar 文件中相应类的类名列表。我需要在运行时使用类名字符串创建这些类的对象。由于在主应用程序中,我没有类的完全限定名称,因为包是在 jar 中定义的,所以我无法加载类和创建对象,所以我将对象创建委托给 jar。我将类名传递给罐子。该 jar 有一个我可以访问的类,因为它由 pf4j 插件管理器加载,并且该类使用反射创建对象并将其返回给我的主应用程序。

    public Job getJob(String jobClass) {
        Job job = null;
        Class<?> clazz = null;
        try {
            clazz = Class.forName("main." + jobClass);
            Constructor<?> ctor = clazz.getConstructor();
            job = (Job) ctor.newInstance();
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException |
                 InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return job;
    }

使用上面的函数我得到了对象但是在主应用程序中是否有另一种方法可以在不使用反射的情况下做到这一点?

【问题讨论】:

    标签: java plugins reflection jar classloader


    【解决方案1】:

    如果您无权访问类的完全限定名称,并且不想使用反射,另一种选择是使用服务提供者接口 (SPI) 模式。

    您可以在插件将实现的主应用程序中定义一个接口。然后,在插件 jar 中,在 META-INF/services 目录下使用接口的完全限定名称创建一个文件。在文件中,列出实现该接口的插件类的完全限定名称。

    在您的主应用程序中,您可以使用 'ServiceLoader' 类来动态加载和实例化插件类。这是一个例子:

        public Job getJob(String jobClass) {
        Job job = null;
        ServiceLoader<Job> loader = ServiceLoader.load(Job.class);
        for (Job plugin : loader) {
            if (plugin.getClass().getName().endsWith("." + jobClass)) {
                job = plugin;
                break;
            }
        }
        if (job == null) {
            throw new RuntimeException("Could not find plugin class: " + jobClass);
        }
        return job;
    }
    

    此代码使用'ServiceLoader' 加载所有实现Job 接口的类,然后查找具有指定名称的类。如果找到,它将返回该类的一个实例。如果没有找到,它会抛出一个'RuntimeException'

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-01
      • 2023-04-05
      • 1970-01-01
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      相关资源
      最近更新 更多