1、Dubbo的通过Wrapper实现AOP例子
阅读此篇文章之前,建议先学习该系列前面几篇文章,会有一个更好的理解
.
参考: Dubbo的SPI机制分析2-Adaptive详解、Dubbo的SPI机制分析3-Dubbo的IOC依赖注入
// 在原有接口、实现类的基础上再加一个Wrapper实现类
public class AdaptiveExtWrapper implements AdaptiveExt {
private AdaptiveExt adaptiveExt;
// 实现一个Wrapper类的关键就是提供一个带类似参数的构造函数,后面代码会分析
public AdaptiveExtWrapper(AdaptiveExt adaptiveExt) {
this.adaptiveExt = adaptiveExt;
}
@Override
public String echo(String msg, URL url) {
// do something,实现了AOP
System.out.println("before");
adaptiveExt.echo(msg, url);
System.out.println("after");
// do something
return "wrapper";
}
}
public class DubboAdaptiveExt implements AdaptiveExt {
private AdaptiveExt adaptiveExt;
// 此处DubboAdaptiveExt依赖注入一个AdaptiveExt 类型的实例,此处测试用例注入的是ThriftAdaptiveExt
public void setAdaptiveExt(AdaptiveExt adaptiveExt) {
this.adaptiveExt = adaptiveExt;
}
@Override
public String echo(String msg, URL url) {
System.out.println(this.adaptiveExt.echo(msg, url));
return "dubbo";
}
}
@Test
public void test1(){
ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);
AdaptiveExt adaptiveExtension = loader.getExtension("dubbo");
URL url = URL.valueOf("test://localhost/test");
adaptiveExtension.echo("d", url);
}
同时记得dubbo的配置文件中要新增一行,否则dubbo框架无法扫描到Wrapper
dubbo=com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExt
cloud=com.alibaba.dubbo.demo.provider.adaptive.impl.SpringCloudAdaptiveExt
thrift=com.alibaba.dubbo.demo.provider.adaptive.impl.ThriftAdaptiveExt
com.alibaba.dubbo.demo.provider.adaptive.impl.AdaptiveExtWrapper
运行代码,输出:
before
thrift
after
2、Dubbo的通过Wrapper实现AOP源码分析
可以发现,上述代码先后输出before、after,中间输出thrift,这其实可以说明adaptiveExtension = loader.getExtension(“dubbo”)返回的是AdaptiveExtWrapper类型的实例,有点像静态代理,下面分析源代码.
// 核心代码,删去一些不重要代码
private T createExtension(String name) {
// 这里也是通过dubbo的SPI机制去扫描dubbo的默认目录下的文件,去加载实现了AdaptiveExt的实现类,这里会
// 加载4个,包括AdaptiveExtWrapper,它就是下面的wrapperClasses中仅有的元素,下面先分析这个加载过程
Class<?> clazz = getExtensionClasses().get(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);
// cachedWrapperClasses,
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
}
}
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
// clazz必须是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.");
}
// 判断clazz是否为标注了@Adaptive注解,后面分析
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());
}
}
// 判断是否是Wrapper类型,后面分析
else if (isWrapperClass(clazz)) {
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
}
// 程序进入此分支,表明clazz是一个普通的拓展类,Robot就是一个普通的拓展类
else {
// 检测clazz是否有默认的构造方法,如果没有,则抛出异常
clazz.getConstructor();
if (name == null || name.length() == 0) {
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) {
Activate activate = clazz.getAnnotation(Activate.class);
if (activate != null) {
cachedActivates.put(names[0], activate);
}
for (String n : names) {
if (!cachedNames.containsKey(clazz)) {
cachedNames.put(clazz, n);
}
Class<?> c = extensionClasses.get(n);
if (c == null) {
// 存储名称到class的映射关系,这样就解析好了一行
extensionClasses.put(n, clazz);
} else if (c != clazz) {
throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
}
}
}
}
}
发表回复