一、ExtensionLoader是什么?作用有哪些?
ExtensionLoader是服务发现、动态加载机制的具体实现。
ExtensionLoader的作用:
1、加载所有打上了@SPI注解的接口,生成动态适配器类,并根据配置动态选择具体的实现类。
2、实现简单ioc,对实现类的依赖属性进行setter注入(就是调用setXXX方法实现赋值)
3、对具体实现类进行包装wrapper,比如Protocol实现,每种具体的Protocol实现都经过 ProtocolListenerWrapper、
PtotocolFilterWrapper、QosProtocolWrapper的联合包装,用以实现服务监听、过滤。
二、重要属性
//spi加载的路径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<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();//缓存每个实现类的实例,key:实现类Class,value:实现类实例private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();//缓存接口实现类对应的别名,比如DubboProtocol类的别名是dubbo,key:实现类Class,value:别名private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();//缓存别名对应的实现类,key:别名,value:实现类Class。特别注意:这里的value是Class,不是实例对象private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>()//??private final Map<String, Object> cachedActivates = new ConcurrentHashMap<>();//缓存实现类的实例对象信息,key:把别名,value:实现类实例对象的包装类private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();//SPI接口实现类实例,这个实例可能是动态生成的接口适配器类,也可能是打了@Adaptive注解的类private final Holder<Object> cachedAdaptiveInstance = new Holder<>();//每个SPI接口类的Adaptive实现类。想要参与SPI机制的接口类上都要打上@SPI注解,每个接口通常都有多种实现。//业务方如果指定实现,便用业务方指定的实现类;否则,使用默认的实现。通常默认的实现类别名在@SPI("dubbo")中//指定。那dubbo是如何支持动态选择实现类的呢?通常,会针对SPI接口生成一个适配器类,比如Protocol的适配器类//Protocol$Adaptive。在适配器中会根据业务参数进行选择具体实现类(实现类加载过后会被缓存到map中)//但如果某个实现类打上了@Adaptive注解,那么这个类就是默认实现,不会再为接口生成适配器类private volatile Class<?> cachedAdaptiveClass = null;//每个接口类的默认实现类的别名private String cachedDefaultName;//包装类,接口实现类的包装类,比如Protocol接口的包装类:ProtocolListenerWrapper、PtotocolFilterWrapper、QosProtocolWrapperprivate Set<Class<?>> cachedWrapperClasses;
三、重要方法
1、ExtensionLoader() : 构造方法
private ExtensionLoader(Class<?> type) {this.type = type;objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());}1)这里可以看出每个SPI接口都有一个ExtensionFactory实现与之对应。每个封装了SPI的ExrtensionLoader都保存着一个objectFactory对象,而objectFactory对象都是ExtensionFactory接口的@Adaptive实现,即AdaptiveExtensionFactory。2)那么这个ExtensionFactory的作用是什么呢?ExtensionLoader在进行ioc,给对象设置依赖的属性值时,objectFactory负责找到依赖的属性值,这个依赖值可能是Spring体系中的bean,也可能是其他的SPI扩展类。其实ExtensionFactory接口有三个实现类,分别AdaptiveExtensionFactory、SpiExtensionFactory、SpringExtensionFactory。AdaptiveExtensionFactory是默认实现,但是没有具体的实现逻辑,它是依赖SpiExtensionFactory和SpringExtensionFactory完成功能的。//factories是个列表,列表中只有两个元素,SpiExtensionFactory和SpringExtensionFactorypublic <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;}
2、getAdaptiveExtension():获取动态适配器
//每个SPI接口都有多种实现类,通常都会把对应的实现类实例后缓存起来(map),然后在构造一个接口的适配器类,//在适配器类中根据业务参数从缓存中动态选择具体的实现,用以完成业务功能public T getAdaptiveExtension() {//判断是否实例化过接口的Adaptive实现(要么是接口的适配器类,要么是接口的@Adaptive实现类)Object instance = cachedAdaptiveInstance.get();if (instance == null) {if (createAdaptiveInstanceError == null) {synchronized (cachedAdaptiveInstance) {instance = cachedAdaptiveInstance.get();if (instance == null) {try {//创建SPI接口的Adaptive实现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;}
3、createAdaptiveExtension():创建SPI接口的Adaptive实现
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);}}Notes:getAdaptiveExtensionClass方法是真正实现的地方,injectExtension方法用以完成ioc功能
4、getAdaptiveExtensionClass():获取SPI接口的Adaptive实现的类信息
private Class<?> getAdaptiveExtensionClass() {getExtensionClasses();if (cachedAdaptiveClass != null) {return cachedAdaptiveClass;}//如果SPI接口类没有@Adaptive实现类,则要创建适配器类return cachedAdaptiveClass = createAdaptiveExtensionClass();}
5、getExtensionClasses():加载SPI接口的各个实现类
private Map<String, Class<?>> getExtensionClasses() {//判断是否加载过SPI接口的实现类Map<String, Class<?>> classes = cachedClasses.get();if (classes == null) {synchronized (cachedClasses) {classes = cachedClasses.get();if (classes == null) {//加载SPI接口的实现类classes = loadExtensionClasses();cachedClasses.set(classes);}}}return classes;}
6、loadExtensionClasses():加载SPI接口的实现类
private Map<String, Class<?>> loadExtensionClasses() {cacheDefaultExtensionName();Map<String, Class<?>> 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():加载SPI接口的实现类
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) {String fileName = dir + type;try {Enumeration<java.net.URL> 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():加载SPI接口的实现类
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {try {try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {String line;while ((line = reader.readLine()) != null) {final int ci = line.indexOf('#');if (ci >= 0) {line = line.substring(0, ci);}line = line.trim();if (line.length() > 0) {try {String name = null;int i = line.indexOf('=');if (i > 0) {name = line.substring(0, i).trim();line = line.substring(i + 1).trim();}if (line.length() > 0) {//实例化加载的实现类loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);}} catch (Throwable t) {IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);exceptions.put(line, e);}}}}} catch (Throwable t) {logger.error("Exception occurred when loading extension class (interface: " +type + ", class file: " + resourceURL + ") in " + resourceURL, t);}}这个功能要结合下面的截图看一下,如下图,实现类是以“别名=类全路径名”,根据类全路径名加载类
9、loadClass():实例化加载的实现类
//类的加载其实在loadResource方法中已经完成了,生成的clazz入参private void loadClass(Map<String, Class<?>> 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.");}//判断该实现类是否有Adaptive注解,是的话就将该实现类赋值给cachedAdaptiveClassif (clazz.isAnnotationPresent(Adaptive.class)) {cacheAdaptiveClass(clazz);//判断该实现类是不是包装类,是的话将该实现类添加入cachedWrapperClasses集合中} 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)) {//??cacheActivateClass(clazz, names[0]);for (String n : names) {//缓存实例类到cachedNames中cacheName(clazz, n);//缓存实例类到extensionClasses中,最终是赋值给cachedClassessaveInExtensionClass(extensionClasses, clazz, n);}}}}
10、createAdaptiveExtensionClass():创建适配器类
private Class<?> createAdaptiveExtensionClass() {//适配器代码类的字符串表示String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();ClassLoader classLoader = findClassLoader();//获取编译类org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();//动态编译生成适配器类return compiler.compile(code, classLoader);}这里以Protocol接口的适配器类举例,详见:https://note.youdao.com/web/#/file/WEB707524014b5f25df84f77a3a8fafedfa/note/WEB4da5d1bb4a6fac5bbd99d32155e11efa/
11、injectExtension():对实现类进行ioc操作
//简单ioc,调用实现类的setXXX方法,为其注入依赖的类private T injectExtension(T instance) {try {if (objectFactory != null) {for (Method method : instance.getClass().getMethods()) {if (isSetter(method)) {if (method.getAnnotation(DisableInject.class) != null) {continue;}Class<?> pt = method.getParameterTypes()[0];if (ReflectUtils.isPrimitives(pt)) {continue;}try {String property = getSetterProperty(method);//这里就是AdaptiveExtensionFactory起作用的地方,找到依赖的类Object object = objectFactory.getExtension(pt, property);if (object != null) {method.invoke(instance, object);}} catch (Exception e) {logger.error("Failed to inject via method " + method.getName()+ " of interface " + type.getName() + ": " + e.getMessage(), e);}}}}} catch (Exception e) {logger.error(e.getMessage(), e);}return instance;}
12、getExtension(String name):根据业务参数获取对应的实现类
public T getExtension(String name) {if (StringUtils.isEmpty(name)) {throw new IllegalArgumentException("Extension name == null");}if ("true".equals(name)) {return getDefaultExtension();}//从cachedInstances中查找name对应的实现类final Holder<Object> holder = getOrCreateHolder(name);Object instance = holder.get();if (instance == null) {synchronized (holder) {instance = holder.get();if (instance == null) {//若name对应的实现类不存在,则创建实现类instance = createExtension(name);holder.set(instance);}}}return (T) instance;}//缓存SPI实现类的包装类Holder。从cachedInstances中查找,有则返回,无则创建private Holder<Object> getOrCreateHolder(String name) {Holder<Object> holder = cachedInstances.get(name);if (holder == null) {cachedInstances.putIfAbsent(name, new Holder<>());holder = cachedInstances.get(name);}return holder;}
13、createExtension(String name):根据业务参数创建SPI实现类
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) {//缓存中若没有name对应的实现类实例,则通过反射生成EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());instance = (T) EXTENSION_INSTANCES.get(clazz);}injectExtension(instance);//这个是精华了,如果SPI接口有相应的包装类,则在此处会对原始invoker进行层层包装,链式调用//以Protocol为例,它的包装类有三个,分别是:Set<Class<?>> wrapperClasses = cachedWrapperClasses;if (CollectionUtils.isNotEmpty(wrapperClasses)) {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 + ") couldn't be instantiated: " + t.getMessage(), t);}}//判断cachedClasses中是否有有效元素,若有则直接返回,若没有则调用loadExtensionClasses方法,//加载一遍SPI接口对应的实现类。以Protocol接口为例,这个cachedClasses中呢应该有DubboProtocol、//RestProtocol、RegistryProtocol等类的class信息private Map<String, Class<?>> getExtensionClasses() {Map<String, Class<?>> classes = cachedClasses.get();if (classes == null) {synchronized (cachedClasses) {classes = cachedClasses.get();if (classes == null) {classes = loadExtensionClasses();cachedClasses.set(classes);}}}return classes;}
