做一个通用的spi机制的工厂类

    1. import lombok.experimental.UtilityClass;
    2. import java.util.*;
    3. /**
    4. * @author shizi
    5. * @since 2020/2/25 上午11:28
    6. */
    7. @UtilityClass
    8. public class ServiceLoaderFactory {
    9. private static final Map<Class, Collection<Object>> SERVICE_MAP = new HashMap<>();
    10. /**
    11. * 初始化某些类
    12. *
    13. * @param interfaceClasses 多个待扩展的spi类型接口
    14. */
    15. public void init(Class<?>... interfaceClasses) {
    16. Arrays.stream(interfaceClasses).forEach(interfaceClass -> {
    17. for (Object instance : ServiceLoader.load(interfaceClass)) {
    18. register(interfaceClass, instance);
    19. }
    20. });
    21. }
    22. /**
    23. * 获取接口类对应的所有spi对象集合
    24. *
    25. * @param interfaceClass 目标接口类
    26. * @param <T> 类型
    27. * @return spi对象集合
    28. */
    29. @SuppressWarnings("unchecked")
    30. public <T> Collection<T> getChildObject(Class<T> interfaceClass) {
    31. return (Collection<T>) SERVICE_MAP.get(interfaceClass);
    32. }
    33. /**
    34. * 获取指定类的对象
    35. *
    36. * @param tClass 目标类
    37. * @param <T> 类型
    38. * @return 目标类的实例
    39. */
    40. @SuppressWarnings("unchecked")
    41. public <T> T getTarget(Class<T> tClass) {
    42. return (T) SERVICE_MAP.entrySet().stream().flatMap(e -> {
    43. if (e.getKey().isAssignableFrom(tClass)) {
    44. return e.getValue().stream();
    45. }
    46. return null;
    47. }).filter(Objects::nonNull).filter(o -> o.getClass().equals(tClass)).findFirst().orElse(null);
    48. }
    49. /**
    50. * 注册目标类以及对应的子类
    51. *
    52. * @param interfaceClass spi对外接口
    53. * @param childInstance 接口的子类
    54. */
    55. private void register(Class interfaceClass, Object childInstance) {
    56. SERVICE_MAP.compute(interfaceClass, (k, v) -> {
    57. if (null == v) {
    58. Collection<Object> valueCollection = new LinkedList<>();
    59. valueCollection.add(childInstance);
    60. return valueCollection;
    61. } else {
    62. v.add(childInstance);
    63. return v;
    64. }
    65. });
    66. }
    67. }

    使用方:

    1. /**
    2. * @author shizi
    3. * @since 2020/2/25 下午2:19
    4. */
    5. public class TestDemo implements LoadServiceDemo {
    6. static {
    7. System.out.println("static fun");
    8. ServiceLoaderFactory.init(LoadServiceDemo.class);
    9. }
    10. @Override
    11. public void testnihao() {
    12. System.out.println("kkk");
    13. }
    14. @Test
    15. public void test1(){
    16. ServiceLoaderFactory.getChildObject(LoadServiceDemo.class).forEach(e->{
    17. e.testnihao();
    18. });
    19. }
    20. @Test
    21. public void test2(){
    22. ServiceLoaderFactory.getTarget(LoadServiceDemoImpl1.class).testnihao();
    23. }
    24. }