扫描Java类路径以查找单独的子类?
我有一个非常独特的情况,我知道我的Java web应用程序总是打包在一个扫描Java类路径以查找单独的子类?,java,reflection,classpath,classloader,war,Java,Reflection,Classpath,Classloader,War,我有一个非常独特的情况,我知道我的Java web应用程序总是打包在一个AbstractWidget的1个且仅1个具体子类中: public abstract class AbstractWidget { // ... } public class SimpleWidget extends AbstractWidget { // ... } public class ComplexWidget extends AbstractWidget { // ... } pu
AbstractWidget
的1个且仅1个具体子类中:
public abstract class AbstractWidget {
// ...
}
public class SimpleWidget extends AbstractWidget {
// ...
}
public class ComplexWidget extends AbstractWidget {
// ...
}
public class CrazyComplexWidget extends AbstractWidget {
// ...
}
// ...etc.
同样,我知道在运行时,我的WAR/WEB-INF/classes
目录将始终包含一个且仅一个AbstractWidget
impl包(不多也不少),无论是ComplexWidget.class
,SimpleWidget.class
,等等
我正在尝试构造代码(当WAR从其ServletContextListener
impl内部启动时实际运行),该代码能够扫描运行时类路径并获得AbstractWidget
的实例(使用public no arg构造函数)
因此,如果我的战争:
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()
,但不确定这是否是正确的方法,即使是正确的方法,也不确定如何在给定的用例中使用它。有什么想法吗?提前谢谢 您可能想检查一下它是否有用于查找给定类的子类的实用程序。你可以用它做类似的事情:
Reflections reflections = new Reflections();
Set<Class<? extends AbstractWidget>> subclasses;
subclasses = reflections.getSubTypesOf(AbstractWidget.class);
反射=新反射();
Set我知道这是一个非常古老的问题,但是类图库可以帮助您非常容易地获得类路径中的所有类,扩展给定类,基本上是给定类的所有子类
梯度依赖
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());
}
Classes which extending 'AbstractWidget' class
com.myorg.some.arbitrary.package.SimpleWidget
假设类路径中有SimpleWidget类,则输出
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());
}
Classes which extending 'AbstractWidget' class
com.myorg.some.arbitrary.package.SimpleWidget
我希望有帮助。ClassGraph是一个非常强大的库,可以满足这个简单的需求。这篇文章解释得很好你事先知道子类的名称吗?谢谢@Joni(+1)-不,这是我的问题。我需要一种方法来描述一个扩展AbstractWidget
的类并搜索它。同样,这些类中只有一个。我想我可能不得不求助于注释,但如果我能避免它们,我更愿意。你怎么知道只有一个,它是否包含在外部进程中?同一个进程可以在配置文件中添加子类的名称吗?再次感谢@Joni(+1)-是的,外部进程打包了WAR(并保证在类路径中的某个地方只包含1个子类)。是的,这个外部进程可能包含一个带有子类名称的配置文件,但这将是非常痛苦的(外部进程是一个遗留系统,我们不再有它的源代码)。所以我不想去探索这个选项,除非它真的是我唯一的解决方案。