Dubbo Wrapper 机制分析
创建测试 demo
package com. luban. dubbo_spi. api ;
@SPI
public interface Car {
public void getColor ( ) ;
}
package com. luban. dubbo_spi. impl ;
public class RedCar implements Car {
public void getColor ( ) {
System . out. println ( "red" ) ;
}
}
package com. luban. dubbo_spi. impl ;
public class CarWrapper implements Car {
private Car car;
public CarWrapper ( Car car) {
System . out. println ( "12" ) ;
this . car = car;
}
@Override
public void getColor ( ) {
car. getColor ( ) ;
}
@Override
public void getColorForUrl ( URL url) {
}
}
然后在 resources 创建一个目录 META-INF.services 目录 并在 META-INF.services 目录中创建文件 com.luban.dubbo_spi.api.Car 一定要与接口同名
red = com.luban.dubbo_spi.impl.RedCar
com.luban.dubbo_spi.impl.CarWrapper
public class CarDemo {
public static void main ( String [ ] args) {
ExtensionLoader < Car > extensionLoader =
ExtensionLoader . getExtensionLoader ( Car . class ) ;
Car redCar = extensionLoader. getExtension ( "red" ) ;
redCar. getColor ( ) ;
}
}
首先通过 ExtensionLoader.getExtensionLoader() 获取加载器
public class CarDemo {
public static void main ( String [ ] args) {
ExtensionLoader < Car > extensionLoader =
ExtensionLoader . getExtensionLoader ( Car . class ) ;
. . .
}
}
在执行 getExtensionLoader() 时,会先判断传入的 Car.class 有没有标注 @SPI 。然后通过 EXTENSION_LOADERS 属性获取是否有创建好的 ExtensionLoader ,没有就执行创建
public class ExtensionLoader < T > {
private static final ConcurrentMap < Class < ? > , ExtensionLoader < ? > > EXTENSION_LOADERS = new ConcurrentHashMap < Class < ? > , ExtensionLoader < ? > > ( ) ;
. . .
public static < T > ExtensionLoader < T > getExtensionLoader ( Class < T > type) {
if ( type == null ) {
throw new IllegalArgumentException ( "Extension type == null" ) ;
}
if ( ! type. isInterface ( ) ) {
throw new IllegalArgumentException ( "Extension type(" + type + ") is not interface!" ) ;
}
if ( ! withExtensionAnnotation ( type) ) {
throw new IllegalArgumentException ( "Extension type(" + type +
") is not extension, because WITHOUT @" + SPI . class . getSimpleName ( ) + " Annotation!" ) ;
}
ExtensionLoader < T > loader = ( ExtensionLoader < T > ) EXTENSION_LOADERS . get ( type) ;
if ( loader == null ) {
EXTENSION_LOADERS . putIfAbsent ( type, new ExtensionLoader < T > ( type) ) ;
loader = ( ExtensionLoader < T > ) EXTENSION_LOADERS . get ( type) ;
}
return loader;
}
}
由于是一次创建,所以 objectFactory 赋值的是 AdaptiveExtensionFactory 。AdaptiveExtensionFactory 创建流程可以参考 『Dubbo SPI源码分析』SPI 机制分析
public class ExtensionLoader < T > {
private final Class < ? > type;
private final ExtensionFactory objectFactory;
. . .
private ExtensionLoader ( Class < ? > type) {
this . type = type;
objectFactory = ( type == ExtensionFactory . class ? null : ExtensionLoader . getExtensionLoader ( ExtensionFactory . class ) . getAdaptiveExtension ( ) ) ;
}
}
获取了 ExtensionLoader 后,开始执行 getExtension() 获取实现的扩展类
public class CarDemo {
public static void main ( String [ ] args) {
ExtensionLoader < Car > extensionLoader =
ExtensionLoader . getExtensionLoader ( Car . class ) ;
Car redCar = extensionLoader. getExtension ( "red" ) ;
. . .
}
}
执行 getExtension() 方法时,先判断缓存实例 cachedInstances 中,是否存在创建的对象,没有的话,则执行 createExtension() 创建
public class ExtensionLoader < T > {
private final ConcurrentMap < String , Holder < Object > > cachedInstances = new ConcurrentHashMap < String , Holder < Object > > ( ) ;
. . .
public T getExtension ( String name) {
if ( StringUtils . isEmpty ( name) ) {
throw new IllegalArgumentException ( "Extension name == null" ) ;
}
if ( "true" . equals ( name) ) {
return getDefaultExtension ( ) ;
}
Holder < Object > holder = cachedInstances. get ( name) ;
if ( holder == null ) {
cachedInstances. putIfAbsent ( name, new Holder < Object > ( ) ) ;
holder = cachedInstances. get ( name) ;
}
Object instance = holder. get ( ) ;
if ( instance == null ) {
synchronized ( holder) {
instance = holder. get ( ) ;
if ( instance == null ) {
instance = createExtension ( name) ;
holder. set ( instance) ;
}
}
}
return ( T ) instance;
}
}
执行 createExtension() 时,先执行 getExtensionClasses() 获取所有扩展类
public class ExtensionLoader < T > {
. . .
private T createExtension ( String name) {
Class < ? > clazz = getExtensionClasses ( ) . get ( name) ;
. . .
}
}
执行 getExtensionClasses() 时,尝试先从 ExtensionLoader 尝试先从自己的缓存集合 cachedClasses 获取集合,如果没有就需要去加载文件获取
public class ExtensionLoader < T > {
private final Holder < Map < String , Class < ? > > > cachedClasses = new Holder < Map < String , 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;
}
}
loadExtensionClasses() 会从几个关键目录中获取对应文件解析后存入集合中返回
public class ExtensionLoader < T > {
private final Class < ? > type;
private static final Pattern NAME_SEPARATOR = Pattern . compile ( "\\s*[,]+\\s*" ) ;
private String cachedDefaultName;
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/" ;
. . .
private Map < String , Class < ? > > loadExtensionClasses ( ) {
final SPI defaultAnnotation = type. getAnnotation ( SPI . class ) ;
if ( defaultAnnotation != null ) {
String value = defaultAnnotation. value ( ) ;
if ( ( value = value. trim ( ) ) . length ( ) > 0 ) {
String [ ] names = NAME_SEPARATOR . split ( value) ;
if ( names. length > 1 ) {
throw new IllegalStateException ( "more than 1 default extension name on extension " + type. getName ( )
+ ": " + Arrays . toString ( names) ) ;
}
if ( names. length == 1 ) {
cachedDefaultName = names[ 0 ] ;
}
}
}
Map < String , Class < ? > > extensionClasses = new HashMap < String , Class < ? > > ( ) ;
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;
}
}
loadDirectory() 先去拼接目录 + 接口名称,得到资源定位符后再去加载文件内容
public class ExtensionLoader < T > {
. . .
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 when load extension class(interface: " +
type + ", description file: " + fileName + ")." , t) ;
}
}
}
解析文件中的每一行内容后,通过 loadClass() 来校验和加载扩展类
public class ExtensionLoader < T > {
. . .
private void loadResource ( Map < String , Class < ? > > extensionClasses, ClassLoader classLoader, java. net. URL resourceURL) {
try {
BufferedReader reader = new BufferedReader ( new InputStreamReader ( resourceURL. openStream ( ) , "utf-8" ) ) ;
try {
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) ;
}
}
}
} finally {
reader. close ( ) ;
}
} catch ( Throwable t) {
logger. error ( "Exception when load extension class(interface: " +
type + ", class file: " + resourceURL + ") in " + resourceURL, t) ;
}
}
}
loadClass() 首先读取的是第一行内容 red = com.luban.dubbo_spi.impl.RedCar 这时候先把类存入 cachedNames 属性中。再遍历下一行 com.luban.dubbo_spi.impl.CarWrapper 把包装类存入 cachedWrapperClasses 属性中,然后返回
重点
判断是否为包装类,只需要判断是否只有包含 Car.class 的构造函数
public class ExtensionLoader < T > {
private final Class < ? > type;
private volatile Class < ? > cachedAdaptiveClass = null ;
private static final Pattern NAME_SEPARATOR = Pattern . compile ( "\\s*[,]+\\s*" ) ;
private final Map < String , Object > cachedActivates = new ConcurrentHashMap < String , Object > ( ) ;
. . .
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 when load extension class(interface: " +
type + ", class line: " + clazz. getName ( ) + "), class "
+ clazz. getName ( ) + "is not subtype of interface." ) ;
}
if ( clazz. isAnnotationPresent ( Adaptive . class ) ) {
if ( cachedAdaptiveClass == null ) {
cachedAdaptiveClass = clazz;
} else if ( ! cachedAdaptiveClass. equals ( clazz) ) {
throw new IllegalStateException ( "More than 1 adaptive class found: "
+ cachedAdaptiveClass. getClass ( ) . getName ( )
+ ", " + clazz. getClass ( ) . getName ( ) ) ;
}
} else if ( isWrapperClass ( clazz) ) {
Set < Class < ? > > wrappers = cachedWrapperClasses;
if ( wrappers == null ) {
cachedWrapperClasses = new ConcurrentHashSet < Class < ? > > ( ) ;
wrappers = cachedWrapperClasses;
}
wrappers. add ( 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 ( names != null && names. length > 0 ) {
. . .
for ( String n : names) {
if ( ! cachedNames. containsKey ( clazz) ) {
cachedNames. put ( clazz, n) ;
}
Class < ? > c = extensionClasses. get ( n) ;
if ( c == null ) {
extensionClasses. put ( n, clazz) ;
} else if ( c != clazz) {
throw new IllegalStateException ( "Duplicate extension " + type. getName ( ) + " name " + n + " on " + c. getName ( ) + " and " + clazz. getName ( ) ) ;
}
}
}
}
}
private boolean isWrapperClass ( Class < ? > clazz) {
try {
clazz. getConstructor ( type) ;
return true ;
} catch ( NoSuchMethodException e) {
return false ;
}
}
}
加载完各个目录的文件后,就会得到对应的 extensionClasses 集合,并根据 name 获取到对应的类,并创建实例。因为在加载时,会把所有的包装类存入 cachedWrapperClasses 集合中,通过遍历,该实例进行包装,最后返回包装的扩展类以供使用
public class ExtensionLoader < T > {
private static final ConcurrentMap < Class < ? > , Object > EXTENSION_INSTANCES = new ConcurrentHashMap < Class < ? > , Object > ( ) ;
. . .
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 ( 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 + ") could not be instantiated: " + t. getMessage ( ) , t) ;
}
}
}
总结