SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。
我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块、xml解析模块、jdbc模块等方案。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 Java SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。
// java.sql.Driver// 1.new一个ServiceLoaderServiceLoader drivers = ServiceLoader.load(Driver.class);Iterator iterator = drivers.iterator();// 2.调用延迟加载器的hashNextwhile (iterator.hasNext()) { // 3.调用延迟加载器的 nextDriver next = iterator.next(); System.out.println(next.getClass());}// result:class com.mysql.jdbc.Driverclass com.mysql.fabric.jdbc.FabricMySQLDriverclass com.alibaba.druid.proxy.DruidDriverclass com.alibaba.druid.mock.MockDriver
ServiceLoader并不会在load的时候去加载所有 接口对应实现类的文件。而是在执行接口的时候去遍历加载。
// 接口全限定名的文件的路径前缀private static final String PREFIX = "META-INF/services/";// 被加载的接口private final Class service;// 类的加载器private final ClassLoader loader;// 创建serviceLoader时 访问控制上下文private final AccessControlContext acc;// 服务缓存池(k-> 类全报名 v-> 实现类信息)private LinkedHashMap providers = new LinkedHashMap<>();// 延迟加载的迭代器private LazyIterator lookupIterator;
// 接口类型Class service;// 接的加载器ClassLoader loader;// META-INF/services/内配置文件的URL集合Enumeration configs = null;// 需加载的实现类的全包名集合Iterator pending = null;// 下一个实现类的全报名,用于迭代器延迟加载的下一个类String nextName = null;
1、load方法
// 1、load方法public static ServiceLoader load(Class service) { // 获取当前线程的类加载器 ClassLoader cl = Thread.currentThread().getContextClassLoader(); // 继续调用重载的方法 return ServiceLoader.load(service, cl);}// 2、调用重载方法public static ServiceLoader load(Class service, ClassLoader loader) { // new 一个ServiceLoader对象 return new ServiceLoader<>(service, loader);}// 3、new 一个serviceLoader对象private ServiceLoader(Class svc, ClassLoader cl) { // PS:服务接口不能为空 service = Objects.requireNonNull(svc, "Service interface cannot be null"); // 指定加载器 loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl; // 指定下上容器(默认为null) acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null; // 刷新:1.重置服务缓冲池 2.new一个延迟加载的迭代器 reload();}// 4、刷新 public void reload() { // 重置服务缓存池 providers.clear(); // 构造一个延迟加载的迭代器 lookupIterator = new LazyIterator(service, loader);}// 5、new LazyIteratorprivate LazyIterator(Class service, ClassLoader loader) { // 指定接口的类信息 this.service = service; // 指定类加载器 this.loader = loader;}
2、获取延迟加载的迭代器
3、调用延迟加载迭代器的hasNext()方法
// 1、调用hasNext()方法public boolean hasNext() { // 默认 acc为null if (acc == null) { // 执行hasNextService()方法 return hasNextService(); } else { PrivilegedAction action = new PrivilegedAction() { public Boolean run() { return hasNextService(); } }; return AccessController.doPrivileged(action, acc); }}// 2、调用hasNextService()方法private boolean hasNextService() { // 默认第一次执行 nextName为null if (nextName != null) { return true;}// 默认第一次执行 configs为null, 通过类加载器加载类的全报名,然后获取URL。if (configs == null) { try { // "META-INF/services/" + java.sql.Driver // 1.file:/Users/zhouzeng/.m2/repository/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar!/META-INF/services/java.sql.Driver // 2.file:/Users/zhouzeng/.m2/repository/com/alibaba/druid/1.0.28/druid-1.0.28.jar!/META-INF/services/java.sql.Driver String fullName = PREFIX + service.getName(); if (loader == null) { configs = ClassLoader.getSystemResources(fullName); } else { configs = loader.getResources(fullName); } } catch (IOException x) { fail(service, "Error locating configuration files", x); } } // 默认第一次执行 pending为null while ((pending == null) || !pending.hasNext()) { if (!configs.hasMoreElements()) { return false; } // 根据 接口+ URL 解析 /** * 1.0 = "com.mysql.jdbc.Driver" 1 = "com.mysql.fabric.jdbc.FabricMySQLDriver" * 2.0 = "com.alibaba.druid.proxy.DruidDriver" 1 = "com.alibaba.druid.mock.MockDriver" **/ pending = parse(service, configs.nextElement()); } // com.mysql.jdbc.Driver nextName = pending.next(); return true;}
4、next()方法
// 1.执行next方法public S next() { // 默认 acc为null if (acc == null) { // 调用nexrService()方法 return nextService(); } else { PrivilegedAction action = new PrivilegedAction() { public S run() { return nextService(); } }; return AccessController.doPrivileged(action, acc); }}// 2.执行nextService()方法private S nextService() { // 判断是否还有下一个类需要加载 if (!hasNextService()) { throw new NoSuchElementException(); } // 1.com.mysql.jdbc.Driver // 2.com.mysql.fabric.jdbc.FabricMySQLDriver // 3.com.alibaba.druid.proxy.DruidDriver // 4.com.alibaba.druid.mock.MockDriver String cn = nextName; nextName = null; Class<?> c = null; try { // 生成接口的实现类 c = Class.forName(cn, false, loader); } catch (ClassNotFoundException x) { fail(service, "Provider " + cn + " not found"); } // 校验实现类 是不是接口的实现类 if (!service.isAssignableFrom(c)) { fail(service, "Provider " + cn + " not a subtype"); } try { // 将实现类的实例,转化为接口类型(类型转化) S p = service.cast(c.newInstance()); // 放到缓存池中 providers.put(cn, p); return p; } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated", x); } throw new Error();}
优点:将业务代码和具体实现类解耦,方便扩展。如需增加新逻辑,无需修改主流程,直接在PI配置文件增加实现类的全限定名即可。
缺点:颗粒度不够细,无法准确定位某一个实现类。要执行就执行所有的实现类。
1.创建一个enableConfiguration
@Configuration@EnableConfigurationProperties({MybatisProperties.class})public class MybatisAutoConfiguration {}
2.在resources下定义META-INF/spring.factories
# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
3.用SpringBoot启动
@SpringBootApplicationpublic class Application extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
在springbot启动时回去加载MybatisAutoConfiguration这个类。
1、在SpringBoot启动时,在refreshContext()时,回去调用@Import的selector。
2、然后执行 AutoConfigurationImportSelector的process()方法 获取对应的configuration的List。
3、由Spring 去加载实例化configuration的配置类。
// 1.SpringBootApplication中的SpringBootConfiguration@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication { @AliasFor(annotation = EnableAutoConfiguration.class) Class<?>[] exclude() default {}; @AliasFor(annotation = EnableAutoConfiguration.class) String[] excludeName() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {};}// 2.SpringBootConfiguration@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {};String[] excludeName() default {};}// 3.查看 AutoConfigurationImportSelector的selectImports()方法public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = this.getAttributes(annotationMetadata); // 获取enableautoconfiguration相关的类 List configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return StringUtils.toStringArray(configurations); }}// 4. 执行getCandidateConfigurations()方法protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { // 获取configurations List configurations = SpringFactoriesLoader.loadFactoryNames( this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations;}// 5. 执行loadFactoryNames()方法public static List loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) { // org.springframework.boot.autoconfigure.EnableAutoConfiguration String factoryClassName = factoryClass.getName(); // 加载spring.fatories的配置项,然后获取key为EnableAutoConfiguration的value return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());}
// 1.spring 资源加载的默认路径public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";// 2.缓存池 K为类加载器 HK为接口全包名 HV为实现类private static final Map> cache = new ConcurrentReferenceHashMap<>();
// 6.执行loadSpringFactories()方法,根据类加载器,获取META-INF/spring.factories下的配置private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) { // 在缓存池中获取,有则直接返回。 MultiValueMap result = cache.get(classLoader); if (result != null) { return result; } try { // 获取"META-INF/spring.factories"的URL Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); result = new LinkedMultiValueMap<>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); for (Map.Entry<?, ?> entry : properties.entrySet()) { List factoryClassNames = Arrays.asList( StringUtils.commaDelimitedListToStringArray((String) entry.getValue())); result.addAll((String) entry.getKey(), factoryClassNames); } } // 将解析出来的数据放到缓存池中。 cache.put(classLoader, result); return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); }}
// 1.定义接口@SPI("wechat")public interface Order { /*** 支付方法** @return 结果*/ String way();}// 2.接口实现AlipayOrderpublic class AlipayOrder implements Order { @Override public String way() { System.out.println("--- 支付宝way() ---"); return "支付宝支付方式"; }}// 3.接口实现WeChatOrderpublic class WeChatOrder implements Order { @Override public String way() { System.out.println("--- 微信way() ---"); return "微信支付方式"; }}
在META-INF/dubbo目录下添加配置文件(com.example.spidemo.dubbo.base.Order)
wechat,wechat2=com.example.spidemo.dubbo.base.impl.WeChatOrder
alipay=com.example.spidemo.dubbo.base.impl.AlipayOrder
public static void test1() { ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Order.class); Order alipay = loader.getExtension("alipay"); System.out.println(alipay.way()); //同一个实现类,多个名称,是同一个实例 Order wechat = loader.getExtension("wechat"); System.out.println(wechat.way()); Order wechat2 = loader.getExtension("wechat2"); System.out.println(wechat2 == wechat); /*** 结果:* --- 支付宝way() ---* 支付宝支付方式* --- 微信way() ---* 微信支付方式* true*/}public static void test2() { ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Order.class); //验证不指定前缀的情况,这里会报错 Order alipay = loader.getDefaultExtension(); System.out.println(alipay.way()); /*** 结果:* Exception in thread "main" java.lang.IllegalArgumentException: Extension name == null* at org.apache.dubbo.common.extension.ExtensionLoader.getExtension(ExtensionLoader.java:340)* at com.example.spidemo.dubbo.adaptive.DubboSpiTest02.main(DubboSpiTest02.java:14)*/}
// 1.构造Order的ExtensionLoader,其中还构造了对应的ExtensionFactory -》AdaptiveExtensionFactory();1.ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Order.class);2.1.loader.getExtension("alipay");2.2.loader.getDefaultExtension();2.3.loader.getAdaptiveExtension();2.4.loader.getActivateExtension(url, "", "online");
// 加载文件的路径// "META-INF/services/"、"META-INF/dubbo/" 、"META-INF/dubbo/internal/"private static final String SERVICES_DIRECTORY = "META-INF/services/";private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";// 存储的是 SPI接口类和ExtensionLoader对象的映射关系 缓存池private static final ConcurrentMap, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();// 存储的是 每个SPI接口的多个实现类和对应实例之间的关系private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();// 接口的类型private final Class<?> type;// 获取工厂类,用于获取Spring容器中的Beanprivate final ExtensionFactory objectFactory;// 扩展类和扩展名称映射关系private final ConcurrentMap, String> cachedNames = new ConcurrentHashMap<>();// 扩展名称和扩展类类型映射关系private final Holder
// 1.ExtensionLoader.getExtensionLoader源码public static ExtensionLoader getExtensionLoader(Class type) { // 接口类不能为空 if (type == null) { throw new IllegalArgumentException("Extension type == null"); } // 必须是接口 if (!type.isInterface()) { throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); } // 必须有@SPI注解 if (!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } // 在ExtensionLoader缓存池中获取 ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type); if (loader == null) { // 不存在,则new一个对应SPI的ExtensionLoader(***重点***) EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type)); // 添加到缓存池中 loader = (ExtensionLoader) EXTENSION_LOADERS.get(type); } return loader;}// withExtensionAnnotation方法private static boolean withExtensionAnnotation(Class type) { return type.isAnnotationPresent(SPI.class);}// 2.new ExtensionLoader(type)源码解析private ExtensionLoader(Class<?> type) { // 设置SPI的类型 this.type = type; // type是不是为ExtensionFactory?是则返回null, 不是则去获取一个ExtensionFactory的ExtensionLoader的适配器扩展器 objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());}// 3.getAdaptiveExtension()方法public T getAdaptiveExtension() { // 从当前的SPI的ExtensionLoader中的缓存池中获取适配器 Object instance = cachedAdaptiveInstance.get(); // dubbo check if (instance == null) { if (createAdaptiveInstanceError == null) { synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 创建一个SPI的适配器扩展器,并放入的缓存池中(***重点***) instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } else { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } } return (T) instance;}// 4.createAdaptiveExtension()方法private T createAdaptiveExtension() { try { // 获取适配器扩展器,然后在获取实例对象,再注入属性(injectExtension,IOC的实现) return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); }}// 5.获取扩展器的适配器private Class<?> getAdaptiveExtensionClass() { // 1.加载默认的扩展器的名称 // 2.加载各个目录下的SPI的服务提供者: // 2.1.如果是适配器,则加载到适配器的缓存中(PS:在方法上加@Adaptive,不会被加载到适配器缓存池中) // 2.2.如果是装饰器,则加载到装饰器的缓存中 // 2.3.加载自动激活的缓存中 // 2.4 加载到缓存cachedNames中(k->class,v->name) getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } // 如果没有扩展器的适配器,则去动态创建一个(比较复杂) return cachedAdaptiveClass = createAdaptiveExtensionClass();}// 6. loadExtensionClasses()方法private Map> loadExtensionClasses() { // 1.获取SPI的value获取默认名字 加载默认的扩展器的名称 cacheDefaultExtensionName(); // 2. 加载各个目录下的SPI的配置文件 // 2.1.如果是适配器,则加载到适配器的缓存中 // 2.2.如果是装饰器,则加载到装饰器的缓存中 // 2.3.把name加载自动激活的缓存中,把name到SPI的name缓存池,把SPI name和类的对应关系缓存到 Map> extensionClasses = new HashMap<>(); loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName()); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); return extensionClasses;}// 7.loadDirectory加载目录下的类private void loadDirectory(Map> extensionClasses, String dir, String type) { String fileName = dir + type; try { Enumeration urls; ClassLoader classLoader = findClassLoader(); if (classLoader != null) { urls = classLoader.getResources(fileName); } else { urls = ClassLoader.getSystemResources(fileName); } if (urls != null) { while (urls.hasMoreElements()) { java.net.URL resourceURL = urls.nextElement(); loadResource(extensionClasses, classLoader, resourceURL); } } } catch (Throwable t) { logger.error("Exception occurred when loading extension class (interface: " + type + ", description file: " + fileName + ").", t); }}// 8.加载资源loadResource// 9.加载类private void loadClass(Map> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException { if (!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Error occurred when loading extension class (interface: " + type + ", class line: " + clazz.getName() + "), class " + clazz.getName() + " is not subtype of interface."); } // 如果是适配器,则加载到适配器的缓存中 if (clazz.isAnnotationPresent(Adaptive.class)) { cacheAdaptiveClass(clazz); // 如果是装饰器,则加载到装饰器的缓存中 } else if (isWrapperClass(clazz)) { cacheWrapperClass(clazz); } else { clazz.getConstructor(); if (StringUtils.isEmpty(name)) { name = findAnnotationName(clazz); if (name.length() == 0) { throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL); } } String[] names = NAME_SEPARATOR.split(name); if (ArrayUtils.isNotEmpty(names)) { // 把name加载自动激活的缓存中 cacheActivateClass(clazz, names[0]); for (String n : names) { // 把name到SPI的name缓存池,把SPI name和类的对应关系缓存到 cacheName(clazz, n); saveInExtensionClass(extensionClasses, clazz, n); } } }}其实我们不难发现上述只是加载的我们SPI对应ExtensionLoader的ExtensionFactory的getAdaptiveExtension()
--> AdaptiveExtensionFactory
// 1.获取Order的名称为"alipay"的SPIpublic T getExtension(String name) { // 校验 if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } // 如果名字为true,则返回默认的SPI if ("true".equals(name)) { return getDefaultExtension(); } // 从cachedInstances缓存池中获取"alipay"的实现类。 final Holder
// loader.getAdaptiveExtension() ,整体逻辑和getExtension("alipay") 差不多。// 唯一有区别的是// getAdaptiveExtension()是createAdaptiveExtension()// getExtension("alipay")是createExtension("alipay")public T getAdaptiveExtension() { // 从适配器缓存池中拿,如果没有则用createAdaptiveExtension()生成一个,再设置到缓存池中。 Object instance = cachedAdaptiveInstance.get(); if (instance == null) { if (createAdaptiveInstanceError == null) { synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 生成适配器类的实例对象instance,并设置到缓存中 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } else { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } } return (T) instance;}// 2.createAdaptiveExtension()private T createAdaptiveExtension() { try { return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); }}// 3.getAdaptiveExtensionClass()private Class<?> getAdaptiveExtensionClass() { // 1.加载默认的扩展器的名称 // 2.加载各个目录下的SPI的服务提供者: // 2.1.如果是适配器,则加载到适配器的缓存中(PS:在方法上加@Adaptive,不会被加载到适配器缓存池中) // 2.2.如果是装饰器,则加载到装饰器的缓存中 // 2.3.加载自动激活的缓存中 // 2.4 加载到缓存cachedNames中(k->class,v->name) getExtensionClasses(); // 如果在适配器的缓存池有对应的适配器类,则返回对应的适配器类 if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } // 如果在适配器缓存池中没有对应的适配类,则创建一个。 return cachedAdaptiveClass = createAdaptiveExtensionClass();}// 4.createAdaptiveExtensionClass() 创建一个适配器类private Class<?> createAdaptiveExtensionClass() { // 生成适配器的源码 String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate(); // 类加载器 ClassLoader classLoader = findClassLoader(); // 通过SPI获取编译器的适配器类,再动态编译这个适配器的源码,生成类。 org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); return compiler.compile(code, classLoader);}// 5.new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();public String generate() { // 如果方法中没有@Adaptive注解,则抛异常 if (!hasAdaptiveMethod()) { throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!"); } StringBuilder code = new StringBuilder(); // 生成package信息 code.append(generatePackageInfo()); // 生成import信息 code.append(generateImports()); // 生成类信息 public class %s$Adaptive implements.... code.append(generateClassDeclaration()); // 获取type的方法,生成方法信息 public %s %s(%s) %s {%s} Method[] methods = type.getMethods(); for (Method method : methods) { code.append(generateMethod(method)); } code.append("}"); if (logger.isDebugEnabled()) { logger.debug(code.toString()); } return code.toString();}
// 1.生成自动激活的扩展类集合public List getActivateExtension(URL url, String key, String group) { // 获取URL的key对应的value String value = url.getParameter(key); // value即name,可以用","分隔 return getActivateExtension(url, StringUtils.isEmpty(value) ? null : COMMA_SPLIT_PATTERN.split(value), group);}// 2,获取getActivateExtension()public List getActivateExtension(URL url, String[] values, String group) { List exts = new ArrayList<>(); List names = values == null ? new ArrayList<>(0) : Arrays.asList(values); // 名字中不包含"-default" if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) { // 1.加载默认的扩展器的名称 // 2.加载各个目录下的SPI的服务提供者: // 2.1.如果是适配器,则加载到适配器的缓存中(PS:在方法上加@Adaptive,不会被加载到适配器缓存池中) // 2.2.如果是装饰器,则加载到装饰器的缓存中 // 2.3.加载自动激活的缓存中(cachedActivates) // 2.4 加载到缓存cachedNames中(k->class,v->name) getExtensionClasses(); for (Map.Entry entry : cachedActivates.entrySet()) { String name = entry.getKey(); Object activate = entry.getValue(); String[] activateGroup, activateValue; if (activate instanceof Activate) { activateGroup = ((Activate) activate).group(); activateValue = ((Activate) activate).value(); } else if (activate instanceof com.alibaba.dubbo.common.extension.Activate) { // 适配alibaba版本的,现在的是apache版本 activateGroup = ((com.alibaba.dubbo.common.extension.Activate) activate).group(); activateValue = ((com.alibaba.dubbo.common.extension.Activate) activate).value(); } else { continue; } // activateGroup中包含了group if (isMatchGroup(group, activateGroup)) { // 获取扩展类的实例 T ext = getExtension(name); if (!names.contains(name) && !names.contains(REMOVE_VALUE_PREFIX + name) && isActive(activateValue, url)) { // 符合上述要求则加到集合中 exts.add(ext); } } } // 根据@Activate 排序 exts.sort(ActivateComparator.COMPARATOR); } List usrs = new ArrayList<>(); for (int i = 0; i < names.size(); i++) { String name = names.get(i); // value的值不是以"-"开始,且 不包含"-"+$name if (!name.startsWith(REMOVE_VALUE_PREFIX) && !names.contains(REMOVE_VALUE_PREFIX + name)) { // 如果名字为"default" if (DEFAULT_KEY.equals(name)) { if (!usrs.isEmpty()) { exts.addAll(0, usrs); usrs.clear(); } } else { // 根据name获取Extension的实例,并放入usrs T ext = getExtension(name); usrs.add(ext); } } } if (!usrs.isEmpty()) { exts.addAll(usrs); } return exts;}
Dubbo 的SPI的优势:
留言与评论(共有 0 条评论) “” |