001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.core.spi; 017 018import io.jboot.utils.AnnotationUtil; 019import io.jboot.utils.ClassScanner; 020import io.jboot.utils.ClassUtil; 021import io.jboot.utils.StrUtil; 022 023import java.util.Iterator; 024import java.util.List; 025import java.util.Objects; 026import java.util.ServiceLoader; 027 028/** 029 * SPI 扩展加载器 030 * <p> 031 * 使用方法: 032 * <p> 033 * 第一步:编写支持扩展点的类,例如MyJbootRpc extends Jbootrpc。 034 * 第二步:给该类添加上注解 JbootSpi, 例如 @JbootSpi("myrpc") MyJbootRpc extends Jbootrpc ... 035 * 第三步:给jboot.properties配置上类型,jboot.rpc.type = myrpc 036 * <p> 037 * 通过这三步,就可以扩展自己的Jbootrpc实现 038 * 039 * @author michael yang 040 */ 041public class JbootSpiLoader { 042 043 044 /** 045 * 通过 SPI 去加载相应的扩展子类 046 * 047 * @param clazz 048 * @param spiName 049 * @param <T> 050 * @return 051 */ 052 public static <T> T load(Class<T> clazz, String spiName, Object... paras) { 053 List<Class<T>> classes = ClassScanner.scanSubClass(clazz, true); 054 if (classes.isEmpty()) { 055 return null; 056 } 057 058 for (Class<T> c : classes) { 059 JbootSpi spiConfig = c.getAnnotation(JbootSpi.class); 060 if (spiConfig != null && spiName.equals(AnnotationUtil.get(spiConfig.value()))) { 061 return ClassUtil.newInstance(c, paras); 062 } 063 //support config class name 064 else if (spiName.equals(c.getName())) { 065 return ClassUtil.newInstance(c, paras); 066 } 067 } 068 069 return null; 070 } 071 072 /** 073 * 通过 SPI 去加载相应的扩展子类 074 * 075 * @param clazz 076 * @param spiName 077 * @param <T> 078 * @return 079 */ 080 public static <T> T load(Class<T> clazz, String spiName) { 081 T returnObject = loadByServiceLoader(clazz, spiName); 082 if (returnObject != null) { 083 return returnObject; 084 } 085 086 if (StrUtil.isBlank(spiName)) { 087 return null; 088 } 089 090 List<Class<T>> classes = ClassScanner.scanSubClass(clazz, true); 091 if (classes.isEmpty()) { 092 return null; 093 } 094 095 for (Class<T> c : classes) { 096 JbootSpi spiConfig = c.getAnnotation(JbootSpi.class); 097 if (spiConfig != null && Objects.equals(spiName, AnnotationUtil.get(spiConfig.value()))) { 098 return ClassUtil.newInstance(c); 099 } 100 //support config class name 101 else if (Objects.equals(spiName, c.getName())) { 102 return ClassUtil.newInstance(c); 103 } 104 } 105 106 return null; 107 } 108 109 /** 110 * 通过 ServiceLoader 加载 111 * 112 * @param clazz 113 * @param spiName 114 * @param <T> 115 * @return 116 */ 117 public static <T> T loadByServiceLoader(Class<T> clazz, String spiName) { 118 ServiceLoader<T> serviceLoader = ServiceLoader.load(clazz); 119 Iterator<T> iterator = serviceLoader.iterator(); 120 121 while (iterator.hasNext()) { 122 T returnObject = iterator.next(); 123 124 if (spiName == null) { 125 return returnObject; 126 } 127 128 JbootSpi spiConfig = returnObject.getClass().getAnnotation(JbootSpi.class); 129 if (spiConfig == null) { 130 continue; 131 } 132 133 if (spiName.equals(AnnotationUtil.get(spiConfig.value()))) { 134 return returnObject; 135 } 136 } 137 138 return null; 139 } 140}