dubbo扩展点 ExtensionLoader
dubbo扩展点加载流程
- 第一步,创建对应的扩展加载类
private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
- 调用getAdaptiveExtension() 进行SPI加载
public class ExtensionLoader<T> {
public T getAdaptiveExtension() {
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError != null) {
throw new IllegalStateException("Failed to create adaptive instance: " +
createAdaptiveInstanceError.toString(),
createAdaptiveInstanceError);
}
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
}
return (T) instance;
}
}
创建AdaptiveExtension
- getAdaptiveExtensionClass()
- newInstance()
- injectExtension() 注入
public class ExtensionLoader<T> {
@SuppressWarnings("unchecked")
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);
}
}
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = 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);
}
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;
}
private Map<String, Class<?>> loadExtensionClasses() {
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
for (LoadingStrategy strategy : strategies) {
loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(),
strategy.overridden(), strategy.excludedPackages());
loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"),
strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
}
return extensionClasses;
}
}
简要知识
- 指定名称的扩展点
ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension("name");
制定名称的扩展点 META-INF/dubbo/internal下 2. 自适应扩展点
ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
标识位扩展点 @Adaptive
// 默认是random这个扩展
@SPI("random")
可以声明类级别和方法级别
- 如果修饰在方法级别,那么会使用javasisit动态创建一个代理类
- 如果修饰类,那么直接返回背修饰的这个类
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
如果存在自适应的扩展点类,那么就直接返回,否则,进行动态创建字节码,然后返回 3. 激活扩展点 类似于spring中的conditionOnBean @Activate
自定义代理处理类
- 自定义代理工厂类
@Slf4j
public class MyJavassistProxyFactory extends AbstractProxyFactory {
@Override
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
log.info("provider getProxy:【{}】", interfaces.getClass().getName());
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
log.info("provider getInvoker:【{}】", type.getName());
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
log.info("provider doInvoke:【{}】-【{}】", type.getName(), methodName);
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
}
- 在resources 添加文件夹META-INF/dubbo/internal
创建文件org.apache.dubbo.rpc.ProxyFactory ,内容如下
myjavassist=com.example.dubbo.MyJavassistProxyFactory
- 修改yml,设置代理类的key为myjavassist
dubbo:
provider:
tag: tag1
proxy: myjavassist
- 完成,启动后日志中就会有如下结果
provider getInvoker:【com.example.dubbo.UserDubboService】
provider getInvoker:【com.example.dubbo.RoleDubboService】
调用时的日志
provider doInvoke:【com.example.dubbo.UserDubboService】-【getUserName】
|