zoukankan      html  css  js  c++  java
  • dubbo怎么做自动注入的?

    通过spi扩展加载的时候,都是通过extensionloader来得到extension的,比如获得一个exchanger:

    public static Exchanger getExchanger(String type) {
    return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type);
    }

    那么就是先拿到自己的extensionloader,然后利用这个loder去拿到extent-name对应的具体的扩展实例。

    对于每一个extensionloader来说,除非自己是ExtensionFactory否则都有一个objectFactory,这个objectFactory本身通过扩展也是一个单例的adaptiveextension。

    private ExtensionLoader(Class<?> type) {
    this.type = type;
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

    通过这个ExtensionLoader去拿到具体的extension的时候:

    injectExtension(instance);
    Set<Class<?>> wrapperClasses = cachedWrapperClasses;
    if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
    for (Class<?> wrapperClass : wrapperClasses) {
    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
    }
    }

    有两种注入,一个是给自己的内部成员注入,另外就是自己被外层wrapper注入,反正都通过injectExtension来做的,具体看这个方法:

    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())) {
    Class<?> pt = method.getParameterTypes()[0];
    try {
    String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
    Object object = objectFactory.getExtension(pt, property);
    if (object != null) {
    method.invoke(instance, object);
    }
    } catch (Exception e) {
    logger.error("fail to inject via method " + method.getName()
    + " of interface " + type.getName() + ": " + e.getMessage(), e);
    }
    }
    }
    }
    }

    就是对所有的set方法对应的属性进行注入,通过objectFactory来完成的,这个factory是一个单例adaptive的,它的具体实现不是通过字节码自动生成的,而是提前写好的:

    public <T> T getExtension(Class<T> type, String name) {
    for (ExtensionFactory factory : factories) {
    T extension = factory.getExtension(type, name);
    if (extension != null) {
    return extension;
    }
    }
    return null;
    }

    对于adaptive来说,它里面含有有两种facotry,spi和spring的,也就是只要有一个能够通过他们两个其中一个找到extension,那么就认为找到。

    对于spi的facotry来说:

    public <T> T getExtension(Class<T> type, String name) {
    if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
    ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
    if (!loader.getSupportedExtensions().isEmpty()) {
    return loader.getAdaptiveExtension();
    }
    }
    return null;
    }

    找到对应的extensionloader(所有的loader都放在全局、静态变量里面),然后直接返回适应性扩展。

    也就是说dubbo帮你注入的不是一个具体extension,实际上也无法拿出来,因为只有在url给定具体的type以后才能给你真正对应的extension。

    而在这里还没有到url解析,所以只返回一个适应性扩展帮你注入。后面如果需要拿到具体的extension,需要结合url才可以做到。这也方便了每个实现者通过url进行自我定义,dubbo只是帮你注入了一个adaptive扩展,具体哪个扩展,你自己结合url去拿。

    对于spring扩展来说:

    public <T> T getExtension(Class<T> type, String name) {
    for (ApplicationContext context : contexts) {
    if (context.containsBean(name)) {
    Object bean = context.getBean(name);
    if (type.isInstance(bean)) {
    return (T) bean;
    }
    }
    }
    return null;
    }

    这个就是依赖spring自己的context,比如定义了一个bean实现,想把它作为prover的imp-ref,那么就用这种方式。

  • 相关阅读:
    数据后台查询分页条件查询数据
    避免js缓存
    jquery点击按钮
    网页内容打印
    数据表的导出
    C#实现字符串按多个字符采用Split方法分割
    JQuery
    AJAX
    JSON
    BOM
  • 原文地址:https://www.cnblogs.com/notlate/p/10229133.html
Copyright © 2011-2022 走看看