栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Dubbo扩展点机制在项目中的应用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Dubbo扩展点机制在项目中的应用

改写自:

Dubbo 源码

实现效果为两种调用方式:

//1. 指定实现类 
Message msg = ExtensionLoader.getExtensionLoader(Serializer.class).getExtension(SerializationTypeEnum.getName(serializeType)).deserialize(clazz, bytes);

//2. 注解上指定接口实现类  
Message msg = ExtensionLoader.getExtensionLoader(Serializer.class).getExtension().deserialize(clazz, bytes);

ExtensionLoader:

package com.fastrpc.extension;

import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;


@Slf4j
public class ExtensionLoader {
    private static final String SERVICES_DIRECTORY = "meta-INF/services/";
    //为每一个接口保存一个加载类
    private static final ConcurrentMap, ExtensionLoader> EXTENSION_LOADERS = new ConcurrentHashMap, ExtensionLoader>();
    private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap, Object>();

    private final Class type;



    //缓存接口的实现类的Class
    private final Holder>> cachedClasses = new Holder>>();
    // 保存Class实例化过的类
    private final ConcurrentMap> cachedInstances = new ConcurrentHashMap>();
    private volatile String cachedDefaultName;

    private ExtensionLoader(Class type) {
        this.type = type;
    }

    
    public static  ExtensionLoader getExtensionLoader(Class type)
    {
        if (type==null)
            throw new IllegalArgumentException("Extension type == null");
        if (!type.isInterface())
            throw new IllegalArgumentException("Extenison type ("+type+") is not interface!");
        if (!withExtensionAnnotation(type))
            throw new IllegalArgumentException("Extension type(" + type +
                    ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
        ExtensionLoader loader= (ExtensionLoader) EXTENSION_LOADERS.get(type);
        if (loader==null)
        {
            EXTENSION_LOADERS.putIfAbsent(type,new ExtensionLoader(type));
            loader= (ExtensionLoader) EXTENSION_LOADERS.get(type);
        }
        return loader;

    }

    
    public static  boolean withExtensionAnnotation(Class type)
    {
        return  (type.isAnnotationPresent(SPI.class));
    }

    
    public T getExtension()
    {
        return getExtension("default");
    }
    
    public T getExtension(String name)
    {
        if (name==null||name.length()==0)
            throw new IllegalArgumentException("Extension name == null");
        //没有指定具体实现类则从SPI中获取指定的实现类
        if("default".equalsIgnoreCase(name))
        {
            return getDefaultExtension();
        }
        Holder holder=cachedInstances.get(name);
        if(holder == null)
        {
            cachedInstances.putIfAbsent(name,new Holder());
            holder=cachedInstances.get(name);
        }

        Object instance=holder.get();
        // double check
        if (instance == null)
        {
            synchronized (holder)
            {
                instance=holder.get();
                if (instance==null)
                {
                    instance=createExtension(name);
                    holder.set(instance);
                }
            }
        }
        return (T) instance;

    }

    private T createExtension(String name) {

        Class clazz=getExtensionClasses().get(name);
        if (clazz==null)
        {
            throw new IllegalArgumentException("No such extension "+name);
        }
        // 注入
        T instance= (T) EXTENSION_INSTANCES.get(clazz);
        if (instance==null){
            try {
                EXTENSION_INSTANCES.putIfAbsent(clazz,clazz.newInstance());
                instance= (T) EXTENSION_INSTANCES.get(clazz);
            } catch (Exception e) {
             log.error(e.getMessage());

            }
        }
        return instance;
    }

    private Map> getExtensionClasses() {
        Map> classes=cachedClasses.get();
        if (classes==null)
        {
            synchronized (cachedClasses)
            {
                classes=cachedClasses.get();
                if (classes==null)
                {
                    // 加载该接口配置的所有扩展类
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }

    
    private Map> loadExtensionClasses() {
        Map> extensionClasses=new HashMap<>();
        loadDirectory(extensionClasses,SERVICES_DIRECTORY);
        return extensionClasses;
    }

    private void loadDirectory(Map> extensionClasses, String dir) {
        String fileName= dir+ type.getName();
        Enumeration urls;
        ClassLoader classLoader=findClassLoader();
        try {
        if (classLoader!=null)
        {
            if (classLoader != null) {
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }
            if (urls != null) {
                while (urls.hasMoreElements()) {
                    java.net.URL resourceURL = urls.nextElement();
                    loadResource(extensionClasses, classLoader, resourceURL);
                }
            }
        }
        } catch (IOException e) {
            log.error("Exception when load extension class(interface: " +
                    type + ", description file: " + fileName + ").", e);
        }
    }
    private void loadResource(Map> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "utf-8"));
            try {
                String line;
                while ((line = reader.readLine()) != null) {
                    final int ci = line.indexOf('#');
                    if (ci >= 0) line = line.substring(0, ci);
                    line = line.trim();
                    if (line.length() > 0) {
                        try {
                            String name = null;
                            int i = line.indexOf('=');
                            if (i > 0) {
                                name = line.substring(0, i).trim();
                                line = line.substring(i + 1).trim();
                            }
                            if (line.length() > 0&&line.length()>0) {
                                loadClass(extensionClasses, classLoader.loadClass(line), name);
                            }
                        } catch (Throwable t) {
                           throw  new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);

                        }
                    }
                }
            } finally {
                reader.close();
            }
        } catch (Throwable t) {
            log.error("Exception when load extension class(interface: " +
                    type + ", class file: " + resourceURL + ") in " + resourceURL, t);
        }
    }

    
    private void loadClass(Map> extensionClasses, Class clazz, String name) {
        if (!type.isAssignableFrom(clazz))
        {
            throw new IllegalStateException("Error when load extension class(interface: "+type+
                    ", class line: "+ clazz.getName()+"), class "+
                    clazz.getName()+ "is not subtype of interface");
        }

         extensionClasses.put(name,clazz);


    }

    private ClassLoader findClassLoader() {
        return ExtensionLoader.class.getClassLoader();
    }

    
    private T getDefaultExtension() {

        if (cachedDefaultName==null)
        {
            SPI defaultAnnotation=type.getAnnotation(SPI.class);
            if (defaultAnnotation !=null)
            {
                String value=defaultAnnotation.value();
                if((value=value.trim()).length()>0)
                {
                    cachedDefaultName=value;

                }
            }else{
                throw new IllegalArgumentException("The implementation class must be specified");
            }
        }
         return getExtension(cachedDefaultName);
    }
}
 

SPI:

package com.fastrpc.extension;

import java.lang.annotation.*;


@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SPI {
    
    String value() default "";
}

Holder:

package com.fastrpc.extension;


public class Holder {
    private volatile T value;

    public T get() {
        return value;
    }

    public void set(T value) {
        this.value = value;
    }
}

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号