【dubbo的IOC实现方法】
dubbo的IOC具体实现在:T injectExtension( T instance )方法中,该方法在3个地方被使用:
ExtensionLoader.getExtensionLoader(Protocol.class)--new ExtensionLoader(type)----getAdaptiveExtension()------createAdaptiveExtension()/**1.为创建好的AdaptiveExtensionClass实例进行属性注入**/--------injectExtension((T) getAdaptiveExtensionClass().newInstance()) /**2.为创建好的Extension实例进行属性注入**/ExtensionLoader.getExtension("dubbo")--createExtension("dubbo")----injectExtension(instance);/**3.为创建好的wrapperClass实例进行属性注入**/----injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)) //
【 injectExtension( T instance )源码】
injectExtension( T instance )方法的作用是通过instance对象的实例的setXxx(object)方法为instance的属性进行赋值,完成setter注入,类似Spring的ioc的经典注入方式。
详细步骤:
1.获取instance的setXxx方法,通过setXxx方法获取属性名称property和属性类型pt。
2.使用objectFactory创建属性property的对象实例object
3.执行method.invoke( instance, object ),注入property实例,即执行setXxx(object)方法
private T injectExtension(T instance) { try { if (objectFactory != null) { for (Method method : instance.getClass().getMethods()) { //成员变量的setXxx(T param)方法,例如:setName(String name) if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { //获取参数param的类型的Class对象 Class pt = method.getParameterTypes()[0]; try { //通过方法名setXxx获取成员变量名xxx,例如setName-->name String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; //实例化参数object Object object = objectFactory.getExtension(pt, property); if (object != null) { //执行instance实例对应的setXxx(object)方法,参数是object method.invoke(instance, object); } } catch (Exception e) { logger.error("fail to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(), e); } } } } } catch (Exception e) { logger.error(e.getMessage(), e); } return instance;}
其中,比较重要的是
Object object = objectFactory.getExtension(pt, property);
这个方法,其中的ExtensionFactory objectFactory实例为 AdaptiveExtensionFactory实例,即
//伪代码ExtensionFactory objectFactory = AdaptiveExtensionFactory实例
AdaptiveExtensionFactory的成员变量
factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]
【 AdaptiveExtensionFactory 类源代码】
/** * AdaptiveExtensionFactory * * @author william.liangf */@Adaptivepublic class AdaptiveExtensionFactory implements ExtensionFactory { private final Listfactories; public AdaptiveExtensionFactory() { ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List list = new ArrayList (); for (String name : loader.getSupportedExtensions()) { list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } /** * 先调用SpiExtensionFactory来实例化 * 如果不行,再使用SpringExtensionFactory来实例化 **/ public T getExtension(Class type, String name) { for (ExtensionFactory factory : factories) { T extension = factory.getExtension(type, name); if (extension != null) { return extension; } } return null; }}
【SpiExtensionFactory源码】
/** * SpiExtensionFactory * * @author william.liangf */public class SpiExtensionFactory implements ExtensionFactory { publicT getExtension(Class type, String name) { //type是接口类型,且必须含有@SPI注解 if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { ExtensionLoader loader = ExtensionLoader.getExtensionLoader(type); //获取type的所有ExtensionClasses实现的key(例如:type是Protocol.class) if (loader.getSupportedExtensions().size() > 0) { //获取type的装饰类,如果有@Adaptive注解的类,则返回该类的实例,否则返回一个动态代理的实例(如:Protocol$Adaptive 的实例) return loader.getAdaptiveExtension(); } } return null; }}
结论:dubbo-spi相对于JDK-spi的一个好处,可以为SPI实现类注入SPI的装饰类或动态代理类。
【 SpringExtendsionFactory的源码 】
/** * SpringExtensionFactory * * @author william.liangf */public class SpringExtensionFactory implements ExtensionFactory { private static final Setcontexts = new ConcurrentHashSet (); public static void addApplicationContext(ApplicationContext context) { contexts.add(context); } public static void removeApplicationContext(ApplicationContext context) { contexts.remove(context); } @SuppressWarnings("unchecked") public T getExtension(Class type, String name) { for (ApplicationContext context : contexts) { //该context是否包含name的bean if (context.containsBean(name)) { //获取该name对应的bean,如果是懒加载或者多实例的bean,此时会实例化name对应的bean Object bean = context.getBean(name); //如果obj的类型是typ或者其子类,与instance相同 if (type.isInstance(bean)) { return (T) bean; } } } return null; }}
【参考文章】
https://www.cnblogs.com/java-zhao/p/7469786.html