dubbo

java spi 机制 java会加载解析项目或者jar包下如:resources\META-INF\services\xyz.luofu.www.CarService(文件)路径下的文件,用户可根据这个特点开发一些可插拔的组件,目录结构及文件:


文件内容:

xyz.luofu.www.RedCar
xyz.luofu.www.BlueCar
public class App 
{
    public static void main( String[] args )
    {
        ServiceLoader<CarService> serviceLoads = ServiceLoader.load(CarService.class); @1

        Iterator<CarService> iterator = serviceLoads.iterator(); //iterator 从这里点进去发现实现了Iterator里面的hasNext,next
        while (iterator.hasNext()){ @2
            CarService next = iterator.next();
            next.color();
        }
}
public class BlueCar implements CarService {
    @Override
    public void color() {
        System.out.println("blue");
    }
}
public class RedCar implements CarService {
    @Override
    public void color() {
        System.out.println("red");
    }
}

接着简单分析下java的spi源码

@1 public static <S> ServiceLoader<S> load(Class<S> service) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        return ServiceLoader.load(service, cl)->ServiceLoader<>(service, loader)
    }
private ServiceLoader(Class<S> svc, ClassLoader cl) {
        service = Objects.requireNonNull(svc, "Service interface cannot be null"); //service即我们传进去的接口
        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
        acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
        reload();
    }
public void reload() {
        providers.clear(); //providers 中存的是接口实现类 此处先清空
        lookupIterator = new LazyIterator(service, loader);
    }
@2 public Iterator<S> iterator() {...
            public boolean hasNext() {...
                return lookupIterator.hasNext()->hasNextService(){...
                  pending = parse(service, configs.nextElement());//解析文件中的每一行
                }
                  nextName = pending.next();//文件中的每一行
            ...}
            }
            public S next() {...
                return lookupIterator.next()->nextService(){...   
                      tring cn = nextName;
                  Class<?> c = null;
                  try {
                      c = Class.forName(cn, false, loader);//根据全类名获取类
                  } catch (ClassNotFoundException x) {
                      S p = service.cast(c.newInstance());//实例化
                      providers.put(cn, p);
                  ...}

dubbo SPI及AOP、IOC实现

public class App 
{
    public static void main( String[] args )
    {
        ExtensionLoader<CarService> extensionLoader = ExtensionLoader.getExtensionLoader(CarService.class); //会检查接口类SPI注解 @1
        extensionLoader.getExtension("red"); @2
        System.out.println( "Hello World!" );
    }
}
@1 getExtensionLoader{...
      ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); //ExtensionLoader 类拓展加载器
        if (loader == null) {
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); //有就取,没有就初始化并且放入一个map
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
...}
private ExtensionLoader(Class<?> type) {
        this.type = type; //接口类
        objectFactory = (type == ExtensionFactory.class ? null :                   ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); //初始化objectFactory @5
    }
@5 getAdaptiveExtension{...
      instance = createAdaptiveExtension()->getAdaptiveExtensionClass{...
            getExtensionClasses();
            if (cachedAdaptiveClass != null) {
              return cachedAdaptiveClass;
            }
            return cachedAdaptiveClass = createAdaptiveExtensionClass();//如果没有Adaptive注解的代理实现类则默认创建一个@6
      ...} ->getExtensionClasses()->..{
            if (clazz.isAnnotationPresent(Adaptive.class)) {
                  if (cachedAdaptiveClass == null) {
                      cachedAdaptiveClass = clazz;  //如果一个子类有 Adaptive注解则认为是接口代理类实现并且放入set,后面   
}
...}
@2 getExtension{...
      instance = createExtension(name); //获取拓展点实现类
...}
createExtension{...
      Class<?> clazz = getExtensionClasses().get(name);
      try {
            T instance = (T) EXTENSION_INSTANCES.get(clazz); //dubbo会有很多类似的缓存结构数据
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            injectExtension(instance); //这里面处理生成代理实现类 @7
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (wrapperClasses != null && !wrapperClasses.isEmpty()) { @4
                for (Class<?> wrapperClass : wrapperClasses) {
                  //这里传red对应的instance实现类返回wrapper,并且循环所有wrapper完成AOP
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
...}
getExtensionClasses->loadExtensionClasses{...
      final SPI defaultAnnotation = type.getAnnotation(SPI.class);
        if (defaultAnnotation != null) {
            String value = defaultAnnotation.value();
            if ((value = value.trim()).length() > 0) {
                String[] names = NAME_SEPARATOR.split(value);...
                if (names.length == 1) {
                    cachedDefaultName = names[0];
                }...
        Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
        //这里会加载几个位置的文件 DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        //加载DUBBO_DIRECTORY = "META-INF/dubbo/";
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        //加载SERVICES_DIRECTORY = "META-INF/services/";
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        
...}
loadDirectory->loadResource{... //这里会把拓展文件传过来,然后读取每一行解析文件
    line = line.substring(i + 1).trim();
    if (line.length() > 0) {
        loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);                      
...}
loadClass{
        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.");
        }
        if (clazz.isAnnotationPresent(Adaptive.class)) {
            if (cachedAdaptiveClass == null) {
                cachedAdaptiveClass = clazz;
            } else if (!cachedAdaptiveClass.equals(clazz)) {
                throw new IllegalStateException("More than 1 adaptive class found: "
                        + cachedAdaptiveClass.getClass().getName()
                        + ", " + clazz.getClass().getName());
            }
        } else if (isWrapperClass(clazz)) { //AOP实现 isWrapperClass-> clazz.getConstructor(type) 判断是否有接口参数的构造 @4
            Set<Class<?>> wrappers = cachedWrapperClasses;
            if (wrappers == null) {
                cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
                wrappers = cachedWrapperClasses;
            }
            wrappers.add(clazz); //添加AOP集合 AOP最后类似装饰器模式
        } else {
            clazz.getConstructor();...
            String[] names = NAME_SEPARATOR.split(name);
            if (names != null && names.length > 0) {...
                for (String n : names) {
                    if (!cachedNames.containsKey(clazz)) {
                        cachedNames.put(clazz, n);
                    }
                    Class<?> c = extensionClasses.get(n);
                    if (c == null) {
                        extensionClasses.put(n, clazz); //把生成的类放进...
    }
@7 injectExtension{...
      if (objectFactory != null) { //这里的objectFactory 生成于 @5
                for (Method method : instance.getClass().getMethods()) {
                  try {
                            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() +             method.getName().substring(4) : "";
                            Object object = objectFactory.getExtension(pt, property); //通过这里进行代理实现类的关联 @8
...}
@6 createAdaptiveExtensionClass{...//生成一个代理类并且编译(得到Url中的属性参数,如:@Adaptive("red") 然后得到getExtension(String))
String code = createAdaptiveExtensionClassCode();
        ClassLoader classLoader = findClassLoader();
        org.apache.dubbo.common.compiler.Compiler compiler =             ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        return compiler.compile(code, classLoader);
...}
createAdaptiveExtensionClassCode{...
      //解析接口方法上是否有Adaptive这个注解如果没有则生成的代理调用时会抛异常,生成的代理类可用Arthas 
      //Arthas(阿尔萨斯)是阿里巴巴开源的 Java 诊断工具 在线查看     
      Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class); 
            StringBuilder code = new StringBuilder(512);
            if (adaptiveAnnotation == null) {
                code.append("throw new UnsupportedOperationException(\"method ")
...}
@8 可以知道objectFactory的代理实现类为AdaptiveExtensionFactory(有@Adaptive修饰)
@Override
    public <T> T getExtension(Class<T> type, String name) {
        for (ExtensionFactory factory : factories) {//SpiExtensionFactory
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }
public class SpiExtensionFactory implements ExtensionFactory {
    @Override
    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;
    }

}

IOP部分相关代码:

@SPI
public interface CarService {
    @Adaptive("red")
    public void color(URL url);
}
posted @ 2020-05-10 15:42  gsluofu  阅读(177)  评论(0编辑  收藏  举报