上一篇主要分析了extensionLoader的获取,以及获取extension的第一种方式,即通过装饰类或者动态代理的方式,今天我们首先从获取extension的第二种方式说起。
/** * Find the extension with the given name. */ getExtension(String name)
下面讨论getExtension(String name)
先从这个方法的代码跟踪开始,
1 public T getExtension(String name) {
2 Holder<Object> holder = cachedInstances.get(name); 3 ......
4 Object instance = holder.get(); 5 ......
6 instance = createExtension(name);
7 return (T) instance; 8 }
这里省略了比较多的内容,有了前面一篇跟踪代码的经验,缓存的具体使用就不再贴出来了,我们只看主要逻辑即可,跟进去看createExtension(name),
1 private T createExtension(String name) { 2 Class<?> clazz = getExtensionClasses().get(name);
3 T instance = clazz.newInstance(); 4
5 injectExtension(instance); 6 Set<Class<?>> wrapperClasses = cachedWrapperClasses;
7 for (Class<?> wrapperClass : wrapperClasses) { 8 instance =
9 injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); 10 }
11 return instance;
12 }
这里先是通过getExtensionClasses().get(name)拿到一个class对象,getExtensionClasses()方法上一篇说过了,它最终所赋值的是type扩展的所有实现中,既没有@Adaptive注解,也不包含type类型的构造器(这一类扩展实现我们称之为包装类)的那些实现类,并且被缓存在cachedClasses map中,map的key即为实现类在dubbo spi配置文件中的类名,这里提一个细节,如果在cachedClasses中没有拿到key为name对应的value,这里就会抛出异常,那也就是说,getExtension(name)这种方式,只能用来获取既非@Adaptive注解,又非包装类的那些类的实现,因为只有这样的类才会被缓存在cachedClasses中。这里拿到这个类并实例化一个Instance,然后调用了方法injectExtension(instance),这个方法看名字就知道了,inject既就是注射的意思,这里就将实现dubbo的依赖注入,现在来看这个方法的实现,
1 private T injectExtension(T instance) {
2 for (Method method : instance.getClass().getMethods()) { 3 if (method.getName().startsWith("set") 4 && method.getParameterTypes().length == 1 5 && Modifier.isPublic(method.getModifiers())) { 6 Class<?> pt = method.getParameterTypes()[0]; 7
8 String property = method.getName().length() > 3 ?
9 method.getName().substring(3, 4).toLowerCase() +
10 method.getName().substring(4) : ""

