面试常问的dubbo的spi机制到底是什么?(下)(三)
第四步:ExtensionAccessorAware接口回调
如果你的接口实现了ExtensionAccessorAware接口,那么会注入给你的bean一个 ExtensionDirector ,ExtensionDirector 可以想象成是ExtensionLoader工厂,可以获取每个接口的ExtensionLoader。
第五步: 初始化后ExtensionPostProcessor回调
调用ExtensionPostProcessor的postProcessAfterInitialization方法对目标对象进行扩展的作用。
第六步:自动包装
到这一步实现类本身的对象就算构造好了,接下来就是进行自动包装,如果wrap是true的话。
自动包装:可以说是静态代理模式,就是对你的目标对象进行代理,怎么代理,就是通过包装类,什么是包装类,在面试常问的dubbo的spi机制到底是什么?(上)有说过,一个一个构造,慢慢构成一个调用链条,最终才会调用到真正的实现类
我们看看源码的实现
@Wrapper注解是个匹配的作用,就是根据需要属性从包装类中选择一批可以用来包装的类。
构造其实很简单,就是当前instance当做包装类的构造参数通过反射构造,然后进行依赖注入,然后将构造出来的对象复制给instance,instance再进行回调之后再赋值给instance,这样往往复复就形成了一个链条。这里我画个图,让大家看看最后构造出来的对象是什么样。
构造后的对象其实就是这样,你最终使用的对象其实是包装对象,如果你获取对象的时候传的wrap参数是true的话,当前默认情况下是true。最后调用的话就会先调用最外层的包装的方法(包装对象2),然后调用(包装对象1)一直调用,最后会调用到真正的目标对象的方法。
为什么需要包装?
很多人可能不清楚,为什么需要包装,其实很好理解,就是起到动态增强目标对象的作用。可以理解为spring中的aop,但是dubbo因为不像spring那样有完整的ioc和aop的实现,dubbo就通过这种包装的方式来实现动态增强目标对象功能的作用。
第七步:Lifecycle接口回调
接下来会调用initExtension方法,这个方法的作用就是判断你的实现类有没有实现Lifecycle接口,如果有的话会调用initialize()方法的实现
至此,一个可用的实现类对象就算完完全全构建完成了,你拿到的对象就是这个对象,然后就会返回这个对象,存到Holder对象中。
最后来张图总结一下实现类构造的过程。
这里我在简单说明一下,
1)包装不是必须的,得看你要获取的对象是什么,如果不要包装,就会回调原始对象的Lifecycle接口,不过dubbo内部的框架基本上获取的都是带包装的对象,而非原始的对象;
2)包装时暴露出去的是包装类的对象,在调用的时候,最先调用的也是包装类的对象,然后一层一层的调用,最终调用到实现类对象。
文章转自公众号:三友的java日记