dubbo(二)dubbo spi机制

1 在介绍dubbo spi机制之前,我们先说一下jdk spi,spi:当服务提供者提供一个接口的多个实现的时候,一般会在META-INF/services/ 下面建立一个与接口全路径同名的文件,在文件里配置接口具体的实现类。当外部调用模块的时候的时候就能实例化对应的实现类而不需要动源码,

2 为什么dubbo不直接用jdk的spi机制,而是自己模仿实现了一个spi机制呢?jdk的spi会在一次实例化所有实现,可能会比较耗时,而且有些可能用不到的实现类也会实例化,浪费资源而且没有选择。另外dubbo的spi增加了对扩展点IOC和AOP的支持,一个扩展点可以直接setter注入其他扩展点。这是jdk spi不支持的。参考博客(https://blog.csdn.net/xujiajun1994/article/details/81023168

下面详细介绍一下spi实现过程,对应的项目,已经上传github(https://github.com/xuws2gj/dubbo-spi.git

1)项目全览

 

1)代码过程解释

package com.shican.spi.loader;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;

import com.shican.spi.annotation.ShiCanSpi;
import com.shican.spi.util.Holder;

public class ShiCanExtensionLoader<T> {

	/** shicanExtension点的路径 */
	private static final String SHICAN_DIRECTORY = "META-INF/SHICAN/";

	/**
	 * 分割SPI上默认拓展点字符串用的
	 */
	private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");

	/** 扩展点加载器的缓存 */
	private static final ConcurrentHashMap<Class<?>, ShiCanExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ShiCanExtensionLoader<?>>();

	/** 扩展点加缓存 */
	private static final ConcurrentHashMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();

	/**
	 * 接口的class
	 */
	private final Class<?> type;

	/** 保存接口ShiCanSpi注解上的值 */
	private String cachedDefaultName;

	/**
	 * 异常记录
	 */
	private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();

	private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
	private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();

	private static <T> boolean withExtensionAnnotation(Class<T> type) {
		return type.isAnnotationPresent(ShiCanSpi.class);
	}

	private ShiCanExtensionLoader(Class<T> type) {
		this.type = type;
	}

	public static <T> ShiCanExtensionLoader<T> getExtensionLoader(Class<T> type) {
		/***
		 * 判断type 接口参数()
		 */
		if (null == type) {
			//第一次进来type  com.shican.spi.car.Car
			throw new IllegalArgumentException("Extension type == null");
		}
		if (!type.isInterface()) {
			throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
		}
		if (!withExtensionAnnotation(type)) {
			throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @"
					+ ShiCanSpi.class.getSimpleName() + " Annotation!");
		}
        //获取spi的加载类,如果是null则new一个出来再放到缓存中(放置map中)
		// ConcurrentHashMap<Class<?>, ShiCanExtensionLoader<?>> EXTENSION_LOADERS

		ShiCanExtensionLoader<T> loader = (ShiCanExtensionLoader<T>) EXTENSION_LOADERS.get(type);
		if (null == loader) {
			EXTENSION_LOADERS.putIfAbsent(type, new ShiCanExtensionLoader<T>(type));
			loader = (ShiCanExtensionLoader<T>) EXTENSION_LOADERS.get(type);
		}
		return loader;
	}

	@SuppressWarnings("unchecked")
	public T getExtension(String name) {
		if (name == null || name.length() == 0)
			throw new IllegalArgumentException("Extension name == null"
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值