0

我有一个相当独特的情况,我知道我的 Java Web 应用程序将始终与 1-and-only-1 具体子类一起打包AbstractWidget

public abstract class AbstractWidget {
    // ...
}

public class SimpleWidget extends AbstractWidget {
    // ...
}

public class ComplexWidget extends AbstractWidget {
    // ...
}

public class CrazyComplexWidget extends AbstractWidget {
    // ...
}

// ...etc.

再一次,我知道在运行时我的WAR/WEB-INF/classes目录将始终包含 1-and-only-1 AbstractWidgetimpl 打包在其中(不多也不少),无论是ComplexWidget.classSimpleWidget.class等等。

我正在尝试构建ServletContextListener能够扫描运行时类路径并获取.AbstractWidget

因此,如果我的 WAR 有:

myWar/
    WEB-INF/
        lib/
        classes/
            com/
                myorg/
                    App (implements ServletContextListener)
                    ... lots of other classes and packages
                    some/
                        arbitrary/
                            package/
                                SimpleWidget

然后,从内部App#contextInitialized(ServletContextEvent)我需要可以SimpleWidget.class在类路径中找到并给我一个实例的代码:

public class App implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent event) {
        // Scan classpath for the lone AbstractWidget impl somehow.
        ???

        // Use public, no-arg ctor to instantiate the impl.
        AbstractWidget widget = ???

        // Now do stuff with widget...
    }
}

我知道您可以使用反射方法Class.isAssignableFrom(),但不确定这是否是正确的方法,即使是正确的方法,如何在我给定的用例中使用它。有任何想法吗?提前致谢!

4

2 回答 2

0

您可能想查看反射 api。 它具有用于查找给定类的子类的实用程序。你可以用它做这样的事情:

Reflections reflections = new Reflections();
Set<Class<? extends AbstractWidget>> subclasses;
subclasses = reflections.getSubTypesOf(AbstractWidget.class);

这将使您在类路径Set中包含该类的所有子AbstractWidget类。http://code.google.com/p/reflections/

于 2013-09-20T16:55:04.367 回答
0

我知道这是一个非常古老的问题,但是 ClassGraph 库可以帮助您非常轻松地获取扩展给定类的类路径中的所有类,基本上是给定类的所有子类。

Gradle 依赖

compile group: 'io.github.classgraph', name: 'classgraph', version: '4.8.46'

这样您就可以轻松地扫描类路径

ScanResult scanResult = new ClassGraph()
    .whitelistPackages("com.myorg") //whatever package you want to scan
    .verbose()
    .enableAllInfo() 
    .scan();

System.out.println("Classes which extending '" + AbstractWidget.class.getSimpleName() + "' class");
ClassInfoList classInfoList = scanResult.getSubclasses(AbstractWidget.class.getName());
for (ClassInfo classInfo : classInfoList) {
    System.out.println("\t" + classInfo.getName());
}

输出假设您在类路径中有 SimpleWidget 类

Classes which extending 'AbstractWidget' class
    com.myorg.some.arbitrary.package.SimpleWidget

我希望它有所帮助。ClassGraph 是一个非常强大的库,可以为这个简单的需求做更多的事情。它在这篇文章中解释得非常好https://readtorakesh.com/java-classpath-scanning-using-classgraph/

于 2020-02-15T18:53:28.970 回答