Java ServiceLoader案例

wen java案例 2

本文目录导读:

Java ServiceLoader案例

  1. 项目结构
  2. 核心代码
  3. 增强版:带优先级和配置的服务
  4. 运行结果示例
  5. 使用 Maven 构建
  6. 重要说明

我来为您提供一个完整的 Java ServiceLoader 案例,包括服务接口、多个实现和实际使用示例。

项目结构

service-loader-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/
│   │   │       ├── service/
│   │   │       │   ├── MessageService.java (接口)
│   │   │       │   └── impl/
│   │   │       │       ├── EmailServiceImpl.java
│   │   │       │       └── SmsServiceImpl.java
│   │   │       └── Main.java (测试类)
│   │   └── resources/
│   │       └── META-INF/
│   │           └── services/
│   │               └── com.example.service.MessageService

核心代码

1 服务接口

package com.example.service;
/**
 * 消息服务接口
 */
public interface MessageService {
    /**
     * 发送消息
     * @param to 接收人
     * @param content 消息内容
     * @return 发送结果
     */
    String sendMessage(String to, String content);
    /**
     * 获取服务类型
     * @return 服务类型名称
     */
    String getServiceType();
}

2 具体实现类

EmailServiceImpl.java:

package com.example.service.impl;
import com.example.service.MessageService;
/**
 * 邮件服务实现
 */
public class EmailServiceImpl implements MessageService {
    @Override
    public String sendMessage(String to, String content) {
        System.out.println("📧 [邮件服务] 发送邮件到: " + to);
        System.out.println("   邮件内容: " + content);
        return "邮件发送成功";
    }
    @Override
    public String getServiceType() {
        return "邮件";
    }
}

SmsServiceImpl.java:

package com.example.service.impl;
import com.example.service.MessageService;
/**
 * 短信服务实现
 */
public class SmsServiceImpl implements MessageService {
    @Override
    public String sendMessage(String to, String content) {
        System.out.println("📱 [短信服务] 发送短信到: " + to);
        System.out.println("   短信内容: " + content);
        return "短信发送成功";
    }
    @Override
    public String getServiceType() {
        return "短信";
    }
}

3 服务配置文件

创建文件 src/main/resources/META-INF/services/com.example.service.MessageService如下:

# 每一行定义一个服务实现类
com.example.service.impl.EmailServiceImpl
com.example.service.impl.SmsServiceImpl

4 测试类

package com.example;
import com.example.service.MessageService;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class Main {
    public static void main(String[] args) {
        // 1. 基本使用
        System.out.println("=== 1. 基本使用 - 获取全部服务 ===");
        getAllServices().forEach(s -> {
            System.out.println("服务类型: " + s.getServiceType());
            s.sendMessage("user@example.com", "Hello!");
            System.out.println();
        });
        System.out.println("=== 2. 使用 Stream API ===");
        List<MessageService> services = loadServices();
        services.stream()
            .filter(s -> s.getServiceType().equals("短信"))
            .findFirst()
            .ifPresent(s -> s.sendMessage("13800138000", "Stream API 过滤测试"));
        System.out.println("\n=== 3. 按类型查找服务 ===");
        getServiceByType("邮件").ifPresent(s -> 
            s.sendMessage("test@example.com", "类型查找测试")
        );
        System.out.println("\n=== 4. 不存在的服务类型 ===");
        getServiceByType("微信").ifPresentOrElse(
            s -> s.sendMessage("", ""),
            () -> System.out.println("未找到微信服务")
        );
        System.out.println("\n=== 5. 自定义加载器 ===");
        ServiceLoader<MessageService> loader = ServiceLoader.load(MessageService.class);
        // 可以通过配置来控制是否懒加载
        ServiceLoader<MessageService> reloadedLoader = loader.reload();
        reloadedLoader.forEach(s -> {
            System.out.println("重新加载服务: " + s.getServiceType());
        });
    }
    /**
     * 获取所有服务实现
     */
    public static List<MessageService> getAllServices() {
        ServiceLoader<MessageService> loader = ServiceLoader.load(MessageService.class);
        List<MessageService> services = new ArrayList<>();
        for (MessageService service : loader) {
            services.add(service);
        }
        return services;
    }
    /**
     * 使用 Stream API 加载服务
     */
    public static List<MessageService> loadServices() {
        ServiceLoader<MessageService> loader = ServiceLoader.load(MessageService.class);
        return StreamSupport.stream(loader.spliterator(), false)
            .collect(Collectors.toList());
    }
    /**
     * 按类型查找服务
     */
    public static Optional<MessageService> getServiceByType(String type) {
        ServiceLoader<MessageService> loader = ServiceLoader.load(MessageService.class);
        return StreamSupport.stream(loader.spliterator(), false)
            .filter(s -> s.getServiceType().equals(type))
            .findFirst();
    }
    /**
     * 扩展:缓存加载的服务
     */
    private static class ServiceCache {
        private static List<MessageService> cachedServices;
        public static synchronized List<MessageService> getServices() {
            if (cachedServices == null) {
                cachedServices = getAllServices();
            }
            return cachedServices;
        }
        public static void clear() {
            cachedServices = null;
        }
    }
}

增强版:带优先级和配置的服务

package com.example.advanced;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 服务优先级注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ServicePriority {
    int value() default 100;
}

增强版服务实例:

package com.example.advanced.impl;
import com.example.advanced.ServicePriority;
import com.example.service.MessageService;
@ServicePriority(10)
public class WeiboServiceImpl implements MessageService {
    @Override
    public String sendMessage(String to, String content) {
        return "微博消息: " + content;
    }
    @Override
    public String getServiceType() {
        return "微博";
    }
}

高级服务加载工具:

package com.example.advanced;
import com.example.service.MessageService;
import com.example.advanced.ServicePriority;
import java.util.*;
import java.util.stream.Collectors;
public class AdvancedServiceLoader {
    private static final Map<String, MessageService> serviceCache = new HashMap<>();
    private static final Map<Class<?>, List<?>> genericCache = new ConcurrentHashMap<>();
    /**
     * 带缓存的服务加载
     */
    public static List<MessageService> loadServicesWithCache() {
        ServiceLoader<MessageService> loader = ServiceLoader.load(MessageService.class);
        List<MessageService> services = new ArrayList<>();
        for (MessageService service : loader) {
            if (!serviceCache.containsKey(service.getClass().getName())) {
                serviceCache.put(service.getClass().getName(), service);
                services.add(service);
            } else {
                services.add(serviceCache.get(service.getClass().getName()));
            }
        }
        return services;
    }
    /**
     * 按优先级排序的服务加载
     */
    public static List<MessageService> loadServicesByPriority() {
        ServiceLoader<MessageService> loader = ServiceLoader.load(MessageService.class);
        return StreamSupport.stream(loader.spliterator(), false)
            .sorted(Comparator.comparingInt(
                s -> getPriority(s.getClass())
            ))
            .collect(Collectors.toList());
    }
    /**
     * 获取服务优先级
     */
    private static int getPriority(Class<?> clazz) {
        ServicePriority annotation = clazz.getAnnotation(ServicePriority.class);
        return annotation != null ? annotation.value() : 100;
    }
    /**
     * 通用服务加载器
     */
    public static <T> List<T> loadAll(Class<T> serviceType) {
        @SuppressWarnings("unchecked")
        List<T> services = (List<T>) genericCache.computeIfAbsent(
            serviceType,
            k -> {
                ServiceLoader<T> loader = ServiceLoader.load(serviceType);
                return StreamSupport.stream(loader.spliterator(), false)
                    .collect(Collectors.toList());
            }
        );
        return services;
    }
}

运行结果示例

=== 1. 基本使用 - 获取全部服务 ===
服务类型: 邮件
📧 [邮件服务] 发送邮件到: user@example.com Hello!
邮件发送成功
服务类型: 短信
📱 [短信服务] 发送短信到: user@example.com Hello!
短信发送成功
=== 2. 使用 Stream API ===
📱 [短信服务] 发送短信到: 13800138000 Stream API 过滤测试
短信发送成功
=== 3. 按类型查找服务 ===
📧 [邮件服务] 发送邮件到: test@example.com 类型查找测试
邮件发送成功
=== 4. 不存在的服务类型 ===
未找到微信服务
=== 5. 自定义加载器 ===
重新加载服务: 邮件
重新加载服务: 短信

使用 Maven 构建

<!-- pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>service-loader-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

重要说明

1 ServiceLoader 特性

  • 懒加载:服务实现只有在首次使用时才会被实例化
  • 自动发现:通过 META-INF/services 目录自动发现服务实现
  • 解耦:服务接口与实现完全解耦,便于扩展

2 使用场景

  • 插件系统开发
  • 数据库驱动加载
  • 日志框架扩展
  • 支付渠道集成
  • 消息推送服务

这个案例展示了 ServiceLoader 的核心用法和高级特性,非常适合理解和应用 Java 的服务发现机制。

抱歉,评论功能暂时关闭!