# Dubbo源码解析:Dubbo SPI是如何实现 AOP,IOC,自适应,自动激活的?

# ExtensionLoader的工作原理
Dubbo在启动的时候默认会扫描这三个目录下的配置,以加载需要的扩展类
/META-INF/services /META-INF/dubbo /META-INF/dubbo/internal
ExtensionLoader是Dubbo SPI中用来加载扩展类的,有如下三个重要方法,搞懂这3个方法基本上就搞懂Dubbo SPI了。
加载扩展类的三种方法如下
- getExtension(),获取普通扩展类
- getAdaptiveExtension(),获取自适应扩展类
- getActivateExtension(),获取自动激活的扩展类
我们以源码中的例子分析Dubbo SPI的实现。
# getExtension(实现自动装载,自动包装,即IOC和AOP)
# 使用例子
获取Exchanger层的实现,通过名字直接获取实现,并没有根据url中的参数获取实现
public class Exchangers {
public static Exchanger getExchanger(String type) {
return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type);
}
}
class ExchangersTest {
@Test
void getExchanger() {
Exchanger header = Exchangers.getExchanger("header");
// org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger@1d8d30f7
System.out.println(header);
}
}
# 实现
// ExtensionLoader
public T getExtension(String name) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
if ("true".equals(name)) {
// 传入的name为true,获取默认的扩展实现类
return getDefaultExtension();
}
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;
}
// ExtensionLoader
private T createExtension(String name) {
// 从配置文件中加载所有的扩展类
// 初始化 cachedWrapperClasses(包装类集合)
// clazz为name对应的实现类
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
// putIfAbsent方法
// 如果key值不存在,则向map中添加
// 如果key值已存在,不会覆盖已有的值,直接返回已经存在的值
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 执行IOC
injectExtension(instance);
// 执行AOP
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
// 找到参数类型为type的构造函数,循环包装
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);
}
}
# getAdaptiveExtension(实现自适应)
标记在类上:将该实现类直接作为默认实现,不再自动生成代码 标记在方法上:生成接口对应的Adaptive类,通过url中的参数来确定最终的实现类
# 用在类上
public class ExtensionLoader<T> {
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
}
public class ExtensionLoaderTest {
@Test
public void spiTest() {
ExtensionFactory extensionFactory = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
//org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory@4abdb505
System.out.println(extensionFactory);
}
}
# 用在方法上
获取网络连接框架的具体实现
public class Transporters {
public static Transporter getTransporter() {
return ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension();
}
}
class TransportersTest {
@Test
void getTransporter() throws IOException {
Transporter transporter = Transporters.getTransporter();
// org.apache.dubbo.remoting.Transporter$Adaptive@49070868
System.out.println(transporter);
}
}
@SPI("netty")
public interface Transporter {
/**
* 启动一个服务
* 当外部调用Transporter#bind方法时,会从URL中提取key为server的value,然后找对应的实现类,没找到再提取key为transporter的value
* 然后找实现类,如果还没找到,则报异常
* @Adaptive 可以进行多个实现类的依次匹配,如果都找不到则抛出异常
*/
@Adaptive({Constants.SERVER_KEY, Constants.TRANSPORTER_KEY})
Server bind(URL url, ChannelHandler handler) throws RemotingException;
/**
* 连接到一个服务
*/
@Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
Client connect(URL url, ChannelHandler handler) throws RemotingException;
}
public class Transporter$Adaptive
implements Transporter {
public Server bind(URL uRL, ChannelHandler channelHandler) throws RemotingException {
if (uRL == null) {
throw new IllegalArgumentException("url == null");
}
URL uRL2 = uRL;
String string = uRL2.getParameter("server", uRL2.getParameter("transporter", "netty"));
if (string == null) {
throw new IllegalStateException(new StringBuffer().append("Failed to get extension (org.apache.dubbo.remoting.Transporter) name from url (").append(uRL2.toString()).append(") use keys([server, transporter])").toString());
}
Transporter transporter = (Transporter)ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(string);
return transporter.bind(uRL, channelHandler);
}
public Client connect(URL uRL, ChannelHandler channelHandler) throws RemotingException {
if (uRL == null) {
throw new IllegalArgumentException("url == null");
}
URL uRL2 = uRL;
String string = uRL2.getParameter("client", uRL2.getParameter("transporter", "netty"));
if (string == null) {
throw new IllegalStateException(new StringBuffer().append("Failed to get extension (org.apache.dubbo.remoting.Transporter) name from url (").append(uRL2.toString()).append(") use keys([client, transporter])").toString());
}
Transporter transporter = (Transporter)ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(string);
return transporter.connect(uRL, channelHandler);
}
}
根据@Adaptive中指定的多个key,依次匹配具体的实现,当没有指定实现类时,抛出异常
# 实现
// ExtensionLoader
private T createAdaptiveExtension() {
try {
// 1. 获取代理对象的一个实例
// 2. 执行ioc
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
private Class<?> getAdaptiveExtensionClass() {
// 从配置文件中加载扩展类
// 如果类上有@Adaptive注册,则赋值给cachedAdaptiveClass
getExtensionClasses();
// 所有的实现类都没有Adaptive,则表示没有代理类
// 如果有代理类,则直接返回代理类
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 没有手动定义代理类,帮你创建代理类
// 创建的过程就是用字符串拼出类的实现,然后编译,逻辑比较多,不分析了
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
# getActivateExtension(实现自动激活)
在Dubbo过滤器一节详细分析把