我们说dubbo的spi机制和Java提供的spi机制,有一个很大的区别,dubbo的spi机制中,需要在文件中,指定key,我们在使用的时候可以根据key,只加载我们需要使用的实现类,那除了直接在文件中,通过
key=com.xxx.interfaceImpl这种方式之外,还可以通过@Extension这个注解来指定key,dubbo源码在解析的时候,会判断,如果没有在文件中指定key,会解析其实现类上是否有这个注解
文章中,指定路径指:META-INF/services
指定文件是指这个路径下的文件
com.alibaba.dubbo.common.extension.ExtensionLoader#loadClass
在spi机制被使用的时候,是会去指定路径下,解析指定的文件,然后从文件中解析出对应key和value,解析之后,会有一系列逻辑的判断,上面的这个方法,就是解析之后,对实现类进行的一系列判断,具体是如何执行到这一个方法的,在前面 dubbo源码之SPI机制源码中有介绍
其实大致就是说:如果在调用spi的时候,会一次去指定路径下解析指定的文件,解析到文件之后,会一行一行的解析,以 "="为分隔符,前面的是key,后面的是value,解析到之后,会根据value(全类名),生成对应的class文件,然后进入到这个方法中,对class进行解析
/**
* 这个方法主要是将name和clazz赋值到extensionClasses中,只是在put之前,会有一系列的逻辑判断,会区分出来是哪种类型的类
* @param extensionClasses
* @param resourceURL
* @param clazz
* @param name
* @throws NoSuchMethodException
*/
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
/**
* 1.判断clazz是否是type的实现类
* 如果type是Protocol,那么这里的clazz就是文件中配置的HttpProtocol实现类
* 如果不是type的实现类,就抛出异常
*/
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error when load extension class(interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + "is not subtype of interface.");
}
/**
* 2.判断当前实现类上是否有@Adaptive注解,需要注意的是:一个接口,只允许有一个adaptive实现类
* 如果有多个,就抛出异常
* cachedAdaptiveClass中保存的就是type对应的adaptive实现类,这里获取到的是我们自己定义的adaptive实现类
*/