在 ExtensionLoader 类的loadFile方法中有下图的这段代码:
类如现在这个ExtensionLoader中的type 是Protocol.class,也就是SPI接口的实现类中XxxProtocol类中有这样的构造函数 public XxxProtocol ( Protocol object) ,这个构造函数显然说明XxxProtocol有包装或代理这个object的意思。所以当发现了这样特点的实现类后,就会把它缓存到wrappers这个变量中,最终缓存在ExtensionLoader的实例属性 cachedWrapperClasses中。
真正进行AOP切面包装的代码是在 createExtension方法中,标红的这段代码:
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, (T) clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } injectExtension(instance); Set> wrapperClasses = cachedWrapperClasses; if (wrapperClasses != null && wrapperClasses.size() > 0) { for (Class> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); //用wrapper类的实例代替原有的instance ,但注意原有的instance作为wrapper的构造参数传入其内部了 } } return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type + ") could not be instantiated: " + t.getMessage(), t); } }
下面通过一个实例来分析下,看这段代码:
@Test public void test(){ ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(Protocol.class) ; Protocol protocol = (Protocol) extensionLoader.getExtension("dubbo") ; System.out.println(protocol ); }
上面这段代码执行后我们会发现输出的对象的类名是com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper,显然得到的protocol对象已经是经过包装了,而且是有两个包装对象类:
com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper 和 com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper ,打开这两个类的源码,我们会发现它们都会有带Protocol参数的构造函数
public ProtocolListenerWrapper(Protocol protocol){ if (protocol == null) { throw new IllegalArgumentException("protocol == null"); } this.protocol = protocol; } public ProtocolFilterWrapper(Protocol protocol){ if (protocol == null) { throw new IllegalArgumentException("protocol == null"); } this.protocol = protocol; }
所以当我们获取Protocol的某个实现时,就会被这两个类所包装。