美文网首页
从dubbo内核分析IOC&AOP

从dubbo内核分析IOC&AOP

作者: 南宋临安府 | 来源:发表于2018-03-11 20:32 被阅读0次

    “载营魄抱一,能无离乎?
    专气致柔,能如婴儿乎?
    涤除玄览,能无疵乎?
    爱民治国,能无以智乎?
    天门开阖,能为雌乎?
    明白四达,能无为乎?
    生之畜之,生而不有,为而不恃,长而不宰,是谓玄德。”[1]

    Spring从诞生至今,ioc和aop一直都是其灵魂所在,至今我们使用spring依然依赖这两大特性:依赖注入(ioc)、面向切面编程(aop)。从设计模式上来讲,却极其简单,无外乎工厂模式和代理模式。
    今天我们从dubbo的内核源码入手,来看看ioc和aop是如何影响着dubbo的框架设计。

    ioc在dubbo中的应用

    dubbo的ioc主要体现在dubbo扩展点加载的环节,T injectExtension(T instance)方法中。该方法只在三个地方被使用:

    createAdaptiveExtension()
     --injectExtension((T) getAdaptiveExtensionClass().newInstance()) //为创建好的AdaptiveExtensionClass实例进行属性注入
     
    createExtension(String name)
     --injectExtension(instance) //为创建好的Extension实例进行属性注入
     --injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)) //为创建好的wrapperClass实例进行属性注入
    

    ExtensionLoader:

        private T injectExtension(T instance) {
            try {
                if (objectFactory != null) {
                    for (Method method : instance.getClass().getMethods()) {
                        if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
                            && Modifier.isPublic(method.getModifiers())) {//一个参数的public的setXXX(T param)方法.例如,setName(String name)
                            Class<?> pt = method.getParameterTypes()[0];//参数param的类型T,eg.String
                            try {
                                String property = method.getName().length() > 3
                                    ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";//获取属性名XXX, eg.name
                                Object object = objectFactory.getExtension(pt, property);//实例化参数
                                if (object != null) {
                                    //执行instance.method(object)方法,这里就是执行instance的setter方法,进行setter注入
                                    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;
        }
    

    整个方法的作用就是通过instance对象实例的setter方法为instance的属性赋值,完成setter注入,即IOC的最经典的注入方式。

    详细步骤:

    • 获取instance的setter方法,通过setter方法获取属性名称property和属性类型pt(即paramType的简写)
    • 使用objectFactory创建一个property名称(类型为pt)的对象实例
    • 执行instance的setter方法,注入property实例

    其中,比较重要的就是:Object object = objectFactory.getExtension(pt, property);这个方法。其中的objectFactory=AdaptiveExtensionFactory实例,其属性factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]。

    看一下源码:

    private final List<ExtensionFactory> factories;
    
        public <T> T getExtension(Class<T> type, String name) {
            /**
             * 先调用SpiExtensionFactory来实例化;
             * 如果不行,再使用SpringExtensionFactory来实例化
             */
            for (ExtensionFactory factory : factories) {
                T extension = factory.getExtension(type, name);
                if (extension != null) {
                    return extension;
                }
            }
            return null;
        }
    

    SpiExtensionFactory:

    public class SpiExtensionFactory implements ExtensionFactory {
        public <T> T getExtension(Class<T> type, String name) {
            if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {//type是接口且必须具有@SPI注解
                ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
                if (loader.getSupportedExtensions().size() > 0) {//获取type的所有ExtensionClasses实现的key
                    return loader.getAdaptiveExtension();//获取type的装饰类,如果有@Adaptive注解的类,则返回该类的实例,否则返回一个动态代理类的实例(例如Protocol$Adpative的实例)
                }
            }
            return null;
        }
    }
    

    从这里我们可以看出dubbo-SPI的另外一个好处:可以为SPI实现类注入SPI的装饰类或动态代理类。

    SpringExtensionFactory:

    public class SpringExtensionFactory implements ExtensionFactory {
        private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
        
        public static void addApplicationContext(ApplicationContext context) {
            contexts.add(context);
        }
    
        public static void removeApplicationContext(ApplicationContext context) {
            contexts.remove(context);
        }
    
        @SuppressWarnings("unchecked")
        public <T> T getExtension(Class<T> type, String name) {
            for (ApplicationContext context : contexts) {
                if (context.containsBean(name)) {//该context是否包含name的bean
                    Object bean = context.getBean(name);//获取name的bean,如果是懒加载或多例的bean,此时会实例化name的bean
                    if (type.isInstance(bean)) {//如果obj的类型是type或其子类,与instanceof相同
                        return (T) bean;
                    }
                }
            }
            return null;
        }
    }
    

    aop在dubbo中的应用

    dubbo在获取扩展点时,会有如下调用:

    final Protocol dubboProtocol = loader.getExtension("dubbo");
    调用层级:

    ExtensionLoader<T>.getExtension()
    --createExtension(String name)
    ----getExtensionClasses().get(name)//获取扩展类
    ------loadExtensionClasses()
    --------loadFile(Map<String, Class<?>> extensionClasses, String dir)
    ----injectExtension(instance);//ioc
    ----wrapper包装;//aop
    

    createExtension(String name),该方法源码如下:

    private T createExtension(String name) {
            /** 从cachedClasses缓存中获取所有的实现类map,之后通过name获取到对应的实现类的Class对象 */
            Class<?> clazz = getExtensionClasses().get(name);
            if (clazz == null) {
                throw findException(name);
            }
            try {
                /** 从EXTENSION_INSTANCES缓存中获取对应的实现类的Class对象,如果没有,直接创建,之后放入缓存 */
                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<Class<?>> wrapperClasses = cachedWrapperClasses;
                if (wrapperClasses != null && wrapperClasses.size() > 0) {
                    for (Class<?> wrapperClass : wrapperClasses) {
                        instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                    }
                }
                return instance;
            } catch (Throwable t) {
                throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
                                                + ")  could not be instantiated: " + t.getMessage(),
                    t);
            }
        }
    

    这里,先给出META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol内容:

    registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
    dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
    filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
    listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
    mock=com.alibaba.dubbo.rpc.support.MockProtocol
    injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol
    rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol
    hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
    com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
    com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
    thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
    memcached=com.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
    redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol
    

    com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper和com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper,这两个类不含有@Adaptive注解且具有含有Protocol的单参构造器,符合这样条件的会被列入AOP增强类。放置在loader的私有属性cachedWrapperClasses中。

    此时的loader:

    • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
    • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
      factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]
    • cachedWrapperClasses = [class ProtocolListenerWrapper, class ProtocolFilterWrapper]

    再来看createExtension(String name)中的红色部分,就是今天的重点AOP。如上所讲,我在cachedWrapperClasses中缓存了两个AOP增强类:class ProtocolListenerWrapper和class ProtocolFilterWrapper。

    首先是获取ProtocolListenerWrapper的单参构造器,然后创建ProtocolListenerWrapper实例,最后完成对ProtocolListenerWrapper实例进行属性注入,注意此时的instance=ProtocolListenerWrapper实例,而不再是之前的DubboProtocol实例了。之后使用ProtocolFilterWrapper以同样的方式进行包装,只是此时ProtocolFilterWrapper包装的是ProtocolListenerWrapper实例。


    1. 老子《道德经》第十章,老子故里,中国鹿邑。

    相关文章

      网友评论

          本文标题:从dubbo内核分析IOC&AOP

          本文链接:https://www.haomeiwen.com/subject/nowwfftx.html