spi 如今已有實現java
1、jdk實現spring
ServiceLoader<DogService> loaders = ServiceLoader.load(DogService.class);
for (DogService d : loaders) { d.sleep(); }
黑色dog。。。汪汪叫,不睡覺... 白色dog。。。呼呼大睡覺...
https://files.cnblogs.com/files/z-test/spi-jdk.rarapp
2、dubbo 裏的spi實現。ide
//獲得一個自適應實現類,用@Adaptive 註解的類,沒有就自動生產一個自適應類,能夠根據調用方法的參數,動態獲取處理類 ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); //獲得默認的實現類 ExtensionLoader.getExtensionLoader(Protocol.class).getDefaultExtension(); //經過名字獲得實現類。獲得實現類,先注入實現類,而後,使用它的包裝類,進行包裝。因此 返回的實例,也多是包裝類的實例 ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("name"); //經過url裏的 key對應的參數獲取實現類。1.先加載默認的激活實現,2加載key對應的value裏的值。 ExtensionLoader.getExtensionLoader(Protocol.class).getActivateExtension(url, key);
建立對應名稱的擴展類代碼測試
@SuppressWarnings("unchecked") private T createExtension(String name) { Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } injectExtension(instance); Set<Class<?>> wrapperClasses = cachedWrapperClasses; if (wrapperClasses != null && !wrapperClasses.isEmpty()) { for (Class<?> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type + ") could not be instantiated: " + t.getMessage(), t); } }
//加載順序 DUBBO_INTERNAL_DIRECTORY,DUBBO_DIRECTORY,SERVICES_DIRECTORY //即用戶能夠覆蓋調源碼裏的實現。 private static final String DUBBO_DIRECTORY = "META-INF/dubbo/"; private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/"; private static final String SERVICES_DIRECTORY = "META-INF/services/";
public int getDefaultPort() { throw new UnsupportedOperationException( "method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!"); } public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException { if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null"); com.alibaba.dubbo.common.URL url = arg0.getUrl(); String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol()); if (extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])"); com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName); return extension.export(arg0); }
public com.alibaba.dubbo.cache.Cache getCache(com.alibaba.dubbo.common.URL arg0, com.alibaba.dubbo.rpc.Invocation arg1) { if (arg0 == null) throw new IllegalArgumentException("url == null"); com.alibaba.dubbo.common.URL url = arg0; if (arg1 == null) throw new IllegalArgumentException("invocation == null"); String methodName = arg1.getMethodName(); String extName = url.getMethodParameter(methodName, "cache", "lru"); if (extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.cache.CacheFactory) name from url(" + url.toString() + ") use keys([cache])"); com.alibaba.dubbo.cache.CacheFactory extension = (com.alibaba.dubbo.cache.CacheFactory) ExtensionLoader .getExtensionLoader(com.alibaba.dubbo.cache.CacheFactory.class).getExtension(extName); return extension.getCache(arg0, arg1); }
public com.alibaba.dubbo.remoting.ChannelHandler dispatch(com.alibaba.dubbo.remoting.ChannelHandler arg0, com.alibaba.dubbo.common.URL arg1) { if (arg1 == null) throw new IllegalArgumentException("url == null"); com.alibaba.dubbo.common.URL url = arg1; String extName = url.getParameter("dispatcher", url.getParameter("dispather", url.getParameter("channel.handler", "all"))); if (extName == null) throw new IllegalStateException( "Fail to get extension(com.alibaba.dubbo.remoting.Dispatcher) name from url(" + url.toString() + ") use keys([dispatcher, dispather, channel.handler])"); com.alibaba.dubbo.remoting.Dispatcher extension = (com.alibaba.dubbo.remoting.Dispatcher) ExtensionLoader .getExtensionLoader(com.alibaba.dubbo.remoting.Dispatcher.class).getExtension(extName); return extension.dispatch(arg0, arg1); }
@Activate(group = {Constants.PROVIDER, Constants.CONSUMER}) 激活的類,適用於getActivateExtension(url, key) 1.先查找適配的@activie對應的類,2,查找url裏key的對應的value所對應的類。url
在 接口類對應的配置文件裏,有兩個實現類,spi 和springspa
@Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { private final List<ExtensionFactory> factories; public AdaptiveExtensionFactory() { ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List<ExtensionFactory> list = new ArrayList<ExtensionFactory>(); for (String name : loader.getSupportedExtensions()) { list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } @Override public <T> T getExtension(Class<T> type, String name) { for (ExtensionFactory factory : factories) { T extension = factory.getExtension(type, name); if (extension != null) { return extension; } } return null; } }
spring 獲取須要注入的對象code
public class SpringExtensionFactory implements ExtensionFactory { private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>(); public static void addApplicationContext(ApplicationContext context) { contexts.add(context); } public static void removeApplicationContext(ApplicationContext context) { contexts.remove(context); } @Override @SuppressWarnings("unchecked") public <T> T getExtension(Class<T> type, String name) { for (ApplicationContext context : contexts) { if (context.containsBean(name)) { Object bean = context.getBean(name); if (type.isInstance(bean)) { return (T) bean; } } } return null; } }
spi對象
public class SpiExtensionFactory implements ExtensionFactory { @Override public <T> T getExtension(Class<T> type, String name) { if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type); if (!loader.getSupportedExtensions().isEmpty()) { return loader.getAdaptiveExtension(); } } return null; } }
你們能夠看看源碼,根據用法介紹裏的方法,跟進看看。blog