使用ClassLoader指向不同路径的ServiceLoader [英] ServiceLoader using ClassLoader pointing to different path
问题描述
几天以来一直在尝试此操作,但无法正常工作!
Have been trying this since few days and can't get it working!
我正在尝试构建一个可插入的Java应用程序,可以在其中从命令行运行它,并在单独的文件夹中提供插件(罐子).看来ServiceLoader
可以满足我的要求,但是我认为我需要一个特殊的情况,即jar不是类路径的一部分,而它们存储在不同的位置,因此,我需要使用ClassLoder
指向其网址到该文件系统路径.
I am trying to build a pluggable java application where I can run it from command line and provide plugins (jars) in a separated folder. It seems the ServiceLoader
would fit my requirement but I think I need a special case where the jars are not part of the classpath whereas they are stored in a different location, and for this reason I would need to use a ClassLoder
pointing its url to this file system path.
我要提供给主应用程序的一个插件是带有一些自定义功能的日志jar.
One of the plugin i want to provide to the main application is a log jar with some custom features.
下面是我正在使用的代码,但无法进入for/loop了.这意味着ServiceLoader
无法识别/匹配任何类实现:
Here below the code I am using , but can't get to go into the for/loop .. it means that the ServiceLoader
is not able to identify/match any class implementation :
final URL u = new File("C:\\data\\myLogJar-1.0-SNAPSHOT.jar").toURI().toURL();
ClassLoader ucl = new URLClassLoader(new URL[] {u});
ServiceLoader<Log> loader = ServiceLoader.load(Log.class, ucl);
for (Iterator<Log> iterator = loader.iterator(); iterator.hasNext(); ) {
System.out.println(iterator.next());
}
loader = ServiceLoader.load(Log.class,ucl);
for (final Log log : loader) {
log.info("Test log");
}
希望您能提供帮助! 非常感谢
I wish you could help! Thanks a lot
==== 添加项目文件:
==== adding project files :
主要可插拔应用程序:
package com.company.dep.automation;
import com.company.dep.automation.pluggable.Log;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
public class Main {
private static ServiceLoader<Log> serviceLoader;
public static void main(String[] args) {
final URL u;
ClassLoader ucl = null;
try {
u = new File("C:\\data\\myLogJar-1.0-SNAPSHOT.jar").toURI().toURL();
ucl = new URLClassLoader(new URL[]{u});
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
ServiceLoader<Log> loader = ServiceLoader.load(Log.class, ucl);
for (Iterator<Log> iterator = loader.iterator(); iterator.hasNext(); ) {
System.out.println(iterator.next());
}
loader = ServiceLoader.load(Log.class, ucl);
for (final Log log : loader) {
log.info("Test log");
}
}
}
日志"插件
界面Log
package com.company.automation.service;
public interface Log {
void trace(String message);
void debug(String message);
void info(String message);
void warn(String message);
void severe(String message);
void error(String message);
void fatal(String message);
}
其实现
package com.company.automation.service.impl;
import com.company.automation.service.Log;
public class LogImpl implements Log {
@Override
public void trace(String message) {
log("TRACE --> " + message);
}
@Override
public void debug(String message) {
log("DEBUG --> " + message);
}
@Override
public void info(String message) {
log("INFO --> " + message);
}
@Override
public void warn(String message) {
log("WARN --> " + message);
}
@Override
public void severe(String message) {
log("SEVERE --> " + message);
}
@Override
public void error(String message) {
log("ERROR --> " + message);
}
@Override
public void fatal(String message) {
log("FATAL --> " + message);
}
private void log(String message) {
System.out.println(message);
}
}
- 结构
=================
=================
按以下方式调整了项目结构,但仍然无效:
Adjusted the project structure as following but still doesnt work :
主应用程序:
扩展程序:
推荐答案
它不起作用,因为它不是同一类Log
,您的主要方法是在jar定义实现时尝试查找com.company.dep.automation.pluggable.Log
的实现com.company.automation.service.Log
的内容,这样ServiceLoader.load
根本找不到任何东西.
It doesn't work because it is not the same class Log
, your main method try to find implementations of com.company.dep.automation.pluggable.Log
while your jar defines an implementation of com.company.automation.service.Log
such that ServiceLoader.load
simply cannot find anything.
您应该使用Main
类将接口com.company.automation.service.Log
从扩展jar移至项目,并在Main
类中导入com.company.automation.service.Log
而不是com.company.dep.automation.pluggable.Log
,然后一切正常.
You should move the interface com.company.automation.service.Log
from the extension jar to the project with your Main
class and import com.company.automation.service.Log
instead of com.company.dep.automation.pluggable.Log
in your Main
class then everything should work.
这篇关于使用ClassLoader指向不同路径的ServiceLoader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!