3.6. 在部署中使用类加载器编程
3.6.1. 在部署中以编程方式载入类和资源 复制链接链接已复制到粘贴板!
您可以以编程方式查找或加载应用程序代码中的类和资源。您选择的方法取决于多个因素。本节介绍可用的方法,并提供了有关何时使用它们的指导。
使用 Class.forName()方法加载类
您可以使用 Class.forName() 方法以编程方式加载和初始化类。这个方法有两个签名:
class.forName(String className):此签名仅取一个参数,即您需要加载的类的名称。通过此方法签名,当前类的类加载程序将加载类并默认初始化新加载的类。
class.forName(String className, boolean initial, ClassLoader loader loader):此签名需要三个参数:类名称、布尔值,指定是否初始化类,以及加载该类的
ClassLoader。
建议使用三个参数签名来以编程方式加载类。通过此签名,您可以控制您是否希望在加载时初始化目标类。获取和提供类加载器也更高效,因为 JVM 不需要检查调用堆栈来确定要使用的类加载程序。假设包含代码的类名为 CurrentClass,您可以使用 CurrentClass .class.getClassLoader() 方法获取类 loader。
以下示例提供了类加载程序来加载并初始化 TargetClass 类:
Class<?> targetClass = Class.forName("com.myorg.util.TargetClass", true, CurrentClass.class.getClassLoader());
Class<?> targetClass = Class.forName("com.myorg.util.TargetClass", true, CurrentClass.class.getClassLoader());
使用给定名称查找所有资源
如果您知道资源的名称和路径,直接加载资源的最佳方法是使用标准 Java 开发套件(JDK) 类或 Class Loader API。
加载单个资源。
若要加载位于与部署中的类或其他类相同的目录中的单个资源,您可以使用
Class.getResourceAsStream()方法。InputStream inputStream = CurrentClass.class.getResourceAsStream("targetResourceName");InputStream inputStream = CurrentClass.class.getResourceAsStream("targetResourceName");Copy to Clipboard Copied! Toggle word wrap Toggle overflow 加载单个资源的所有实例。
要加载对您部署的类 loader 可见的单个资源的所有实例,请使用
Class.getClassLoader().getResources(String resourceName)方法,其中resourceName是资源的完全限定路径。此方法为类加载器使用给定名称访问的资源返回所有URL对象的枚举。然后,您可以使用openStream()方法迭代 URL 数组以打开各个流。下例加载资源的所有实例,并迭代结果。
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注意由于 URL 实例是从本地存储加载的,因此不需要使用
openConnection()或其他相关方法。流更易于使用并最小化代码的复杂性。从类加载器加载类文件。
如果已经载入了一个类,您可以使用以下语法载入与该类对应的类文件:
InputStream inputStream = CurrentClass.class.getResourceAsStream(TargetClass.class.getSimpleName() + ".class");
InputStream inputStream = CurrentClass.class.getResourceAsStream(TargetClass.class.getSimpleName() + ".class");Copy to Clipboard Copied! Toggle word wrap Toggle overflow 如果还没有载入该类,则必须使用类加载器并转换路径:
String className = "com.myorg.util.TargetClass" InputStream inputStream = CurrentClass.class.getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");String className = "com.myorg.util.TargetClass" InputStream inputStream = CurrentClass.class.getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");Copy to Clipboard Copied! Toggle word wrap Toggle overflow
3.6.2. 编程化部署中的资源 复制链接链接已复制到粘贴板!
JBoss 模块库为迭代所有部署资源提供了多个 API。JBoss 模块 API 的 Java 文档位于以下位置 :http://docs.jboss.org/jbossmodules/1.3.0.Final/api/.要使用这些 API,您必须在 MANIFEST.MF 中添加以下依赖项:
Dependencies: org.jboss.modules
Dependencies: org.jboss.modules
务必要注意,尽管这些 API 提供了更大的灵活性,但它们的运行也比直接路径查找慢得多。
本节介绍了您可以编程化地迭代应用程序代码中的资源的一些方法。
列出部署中和所有导入中的资源。
有时无法通过确切的路径查找资源。例如,确切的路径可能未知,或者您可能需要检查给定路径中的多个文件。在本例中,JBoss 模块库为迭代所有部署资源提供了多个 API。您可以使用以下两种方法之一迭代部署中的资源:
迭代单一模块中找到的所有资源。
ModuleClassLoader.iterateResources()方法迭代此模块类加载程序中的所有资源。此方法采用两个参数:要搜索的起始目录名和一个布尔值,指定它是否应递归到子目录中。以下示例演示了如何获取 ModuleClassLoader 并获取
bin/目录中资源的迭代器,并递归到子目录。ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = moduleClassLoader.iterateResources("bin",true);ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = moduleClassLoader.iterateResources("bin",true);Copy to Clipboard Copied! Toggle word wrap Toggle overflow 生成的迭代器可用于检查每个匹配资源并查询其名称和大小(如果可用),打开可读流,或获取资源的 URL。
迭代单一模块和导入的资源中找到的所有资源。
Module.iterateResources()方法迭代此模块类加载程序中的所有资源,包括导入模块中的资源。此方法返回的集合比之前的方法大得多。这个方法需要一个参数,它是将结果缩小到特定模式的过滤器。或者,也可以提供 PathFilters.acceptAll()来返回整个集合。以下示例演示了如何在此模块中查找整个资源集合,包括导入。
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.acceptAll());
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.acceptAll());Copy to Clipboard Copied! Toggle word wrap Toggle overflow
查找与某一模式匹配的所有资源。
如果您只需要在部署中或部署的完整导入集中找到特定资源,则需要过滤资源迭代。JBoss 模块过滤 API 为您提供了多个工具来实现这一目标:
检查完整的依赖项。
如果您需要检查完整的依赖项集合,您可以使用
Module.iterateResources()方法的PathFilter参数检查每个资源的匹配名称。检查部署依赖项。
如果您只需要在部署中查看,请使用
ModuleClassLoader.iterateResources()方法。但是,您必须使用其他方法过滤生成的迭代器。PathFilters.filtered()方法可以提供本例中资源迭代器的过滤视图。PathFilters类包含许多静态方法,用于创建和编写可执行各种功能的过滤器,包括查找子路径或精确匹配项或匹配 Ant 风格的"glob"模式。
过滤资源的其他代码示例。
以下示例演示了如何根据不同的条件过滤资源。
示例:查找所有文件命名
的消息.properties(在您的部署中)ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/messages.properties"), moduleClassLoader.iterateResources("", true));ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/messages.properties"), moduleClassLoader.iterateResources("", true));Copy to Clipboard Copied! Toggle word wrap Toggle overflow 示例:在您的部署和导入中查找所有文件命名
的消息.propertiesModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.match("**/message.properties"));ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.match("**/message.properties"));Copy to Clipboard Copied! Toggle word wrap Toggle overflow 示例:查找任何在您的部署中命名
my-resources的所有文件ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/my-resources/**"), moduleClassLoader.iterateResources("", true));ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/my-resources/**"), moduleClassLoader.iterateResources("", true));Copy to Clipboard Copied! Toggle word wrap Toggle overflow 示例:查找部署和导入中
的所有文件命名的消息或错误ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.any(PathFilters.match("**/messages"), PathFilters.match("**/errors"));ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.any(PathFilters.match("**/messages"), PathFilters.match("**/errors"));Copy to Clipboard Copied! Toggle word wrap Toggle overflow 示例:查找部署中特定软件包中的所有文件
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = moduleClassLoader.iterateResources("path/form/of/packagename", false);ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = moduleClassLoader.iterateResources("path/form/of/packagename", false);Copy to Clipboard Copied! Toggle word wrap Toggle overflow