我试图理解 Java 的ServiceLoader概念、工作机制和具体用例,但发现官方文档太抽象和混乱。
首先,文档概述了服务和服务提供商。服务是一组接口和抽象类,封装在一个 jar 档案(API 库)中。服务提供者是一组实现或扩展 API 的类,封装在一个不同的 jar 文件(提供者库)中。
到目前为止一切顺利,但随后文档变得混乱。
出于加载的目的,服务由单一类型表示,即单一接口或抽象类。(可以使用具体类,但不建议这样做。)给定服务的提供者包含一个或多个具体类,这些类使用特定于提供者的数据和代码扩展该服务类型。提供者类通常不是整个提供者本身,而是一个代理,它包含足够的信息来决定提供者是否能够满足特定请求以及可以按需创建实际提供者的代码。提供者类的细节往往是高度特定于服务的;没有任何一个类或接口可以统一它们,所以这里没有定义这样的类型。
那么实际上Service type和Provider class 是什么?我的印象是,服务类型是API 库中的一个门面,提供者类是提供者库中这个门面接口的实现,即ServiceLoader实际加载的类。这样对吗?但对我来说,所有组件如何联系在一起仍然没有多大意义。
提供者类作为代理来决定提供者是否能够满足特定请求以及可以按需创建实际提供者的代码是什么意思?无法在何处定义统一类型?基本上所有这一段都令人困惑,我想通过一个具体的例子听到更容易理解的解释。
然后关于提供者配置文件...
通过在资源目录 META-INF/services 中放置一个提供者配置文件来识别服务提供者。该文件的名称是服务类型的完全限定二进制名称。该文件包含具体提供者类的完全限定二进制名称列表,每行一个...
命名特定提供程序的配置文件不必与提供程序本身位于同一 jar 文件或其他分发单元中。提供者必须可以从最初查询以定位配置文件的同一个类加载器访问;请注意,这不一定是实际加载文件的类加载器。
这是否意味着对于服务类型为 org.foo.BarServiceType 的 API,在类路径中必须存在具有实现此类型的类的提供程序 jar和 META-INF/services/org.foo.BarServiceType列出此提供程序类的命名提供程序配置文件,所有这些都可以通过Classloader加载ServiceLoader查找的相同访问并在 API 上绑定提供者?
从类加载器的角度来看,可访问意味着提供者配置文件和提供者库可以在包的外部提供,在层次结构的上层,即从容器或其他中间件。
提供者配置文件列出了提供者类,并且可能捆绑在提供者包中(如果捆绑了为什么它会列出多个类?)或来自外部。但是哪种方法更常见:在提供者之间提供配置文件,还是从 API 库本身提供列出一组支持的提供者的文件?还是后者是一种误解?
最后关于 ServiceLoader
在哪里ServiceLoader实际实例化并调用以加载服务提供者?这是否发生在API 库提供的工厂方法中?例如,不LoggingFactory.getLogger(clazz)的SLF4J内部委托给ServiceLoader,它使用反射来读取提供者配置文件并加载服务?
服务加载机制如何处理存在多个提供者及其配置文件的情况,或者有提供者配置文件条目但没有类本身的情况?
ServiceLoader日志框架之外的其他一些具体用例是什么?它在Java …
如何让嵌入式tomcat通过logback写入日志?我找到了一些关于使用log4j的独立tomcat的信息.但是嵌入式tomcat和logback的设置如何?
这些是maven依赖项:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-log4j</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${sl4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${sl4j.version}</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
我知道Spring Boot会自动执行tomcat日志记录集成.但在这种情况下我不能使用Spring.
我在我的java应用程序中使用嵌入式tomcat。下面是我的源代码。但是 tomcat 没有生成任何日志。
embedded = new Embedded();
embedded.setDebug(3);
org.apache.catalina.logger.FileLogger embeddedFileLogger = new org.apache.catalina.logger.FileLogger();
embeddedFileLogger.setDirectory(tomcatHome+"/log");
embeddedFileLogger.setPrefix("Embedded_log_");
embeddedFileLogger.setSuffix(".txt");
embeddedFileLogger.setTimestamp(true);
embeddedFileLogger.setVerbosity(3);
//embedded.setLogger(new SystemOutLogger());
engine = embedded.createEngine();
//engine.setLogger(embeddedFileLogger);
embeddedFileLogger.setContainer(engine);
engine.setDefaultHost("localhost");
host = embedded.createHost("localhost", tomcatHome + "/webapps");
//host.setLogger(embeddedFileLogger);
engine.addChild(host);
_context = embedded.createContext("", tomcatHome + "/webapps/ROOT");
host.addChild(_context);
embedded.addEngine(engine);
CoyoteConnector connector = (CoyoteConnector)embedded.createConnector(InetAddress.getByName(ipAddress), port, false);
embedded.addConnector(connector);
embedded.setLogger(embeddedFileLogger);
embedded.start();
Run Code Online (Sandbox Code Playgroud)
请让我知道如何通过代码或 tomcat 配置启用嵌入式 tomcat 日志记录。