Server Provider Interface,服务发现机制。将接口实现类的全限定名配置在文件中,并由服务加载读取配置文件,加载实现类。
java 通过 ServiceLoader 类实现,定义在目录 META-INF/services 文件夹,在里面定义具体的实现类。通过反射获取实例。
破坏了双亲委派机制,参考:双亲委派机制
根据接口名调用 ServerLoader.load(), 根据约定找到 META-INF/services 目录,解析文件得到实现类的全限定名,然后循环 通过反射方法Class.forName()加载类,和通过newInstance() 将类实例化,并将实例化的类缓存到List对象,然后返回。
先寻找当前线程绑定的ClassLoader,如果没有就是使用SystemClassLoader
然后清除缓存,创建一个LazyIterator
public static <S > ServiceLoader <S > load (Class <S > service ) {
// 获取当前线程的ClassLoader
ClassLoader cl = Thread .currentThread ().getContextClassLoader ();
return ServiceLoader .load (service , cl );
}
private ServiceLoader (Class <S > svc , ClassLoader cl ) {
service = Objects .requireNonNull (svc , "Service interface cannot be null" );
// 如果没有则使用SystemClassLoader
loader = (cl == null ) ? ClassLoader .getSystemClassLoader () : cl ;
acc = (System .getSecurityManager () != null ) ? AccessController .getContext () : null ;
reload ();
}
public void reload () {
// 清空缓存、再创建一个LazyIterator
providers .clear ();
lookupIterator = new LazyIterator (service , loader );
}
调用hasNext()来做实例循环
调用next() 得到一个实例
public boolean hasNext () {
if (acc == null ) {
return hasNextService ();
} else {
PrivilegedAction <Boolean > action = new PrivilegedAction <Boolean >() {
public Boolean run () { return hasNextService (); }
};
return AccessController .doPrivileged (action , acc );
}
}
public S next () {
if (acc == null ) {
return nextService ();
} else {
PrivilegedAction <S > action = new PrivilegedAction <S >() {
public S run () { return nextService (); }
};
return AccessController .doPrivileged (action , acc );
}
}
获取文件的位置,加载配置文件
按行遍历文件内容,解析内容,赋给nextName集合
Iterator <String > pending = null ;
private boolean hasNextService () {
if (nextName != null ) {
return true ;
}
if (configs == null ) {
try {
// 得到文件的位置
String fullName = PREFIX + service .getName ();
if (loader == null )
// 加载配置文件
configs = ClassLoader .getSystemResources (fullName );
else
configs = loader .getResources (fullName );
} catch (IOException x ) {
fail (service , "Error locating configuration files" , x );
}
}
// 按行遍历文件内容
while ((pending == null ) || !pending .hasNext ()) {
if (!configs .hasMoreElements ()) {
return false ;
}
// 解析内容
pending = parse (service , configs .nextElement ());
}
nextName = pending .next ();
return true ;
}
通过解析到的全限定名加载类,并且创建实例放入缓存中,之后返回实例
private S nextService () {
if (!hasNextService ())
throw new NoSuchElementException ();
// 获取当前解析到的实现类全限定名
String cn = nextName ;
nextName = null ;
Class <?> c = null ;
try {
// 加载指定的实现类
c = Class .forName (cn , false , loader );
}
···················
try {
// 创建实现类
S p = service .cast (c .newInstance ());
// 缓存实现类
providers .put (cn , p );
return p ;
}
················
}
不能按需加载,需要遍历所有的实现,并实例化,然后在循环中才能找到我们需要的实现。如果不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费 。
配置文件中只是简单的列出了所有的拓展实现,而没有给他们命名,导致获取某个实现类的方式不够灵活,只能通过循环的形式获取,不能根据某个参数来获取对应的实现类 。
扩展之间彼此存在依赖,做不到自动注入和装配,不提供上下文的IOC和AOP功能。
扩展很难和其他的容器框架集成,比如扩展依赖一个外部Spring容器中的bean,原生的JDK SPI并不支持。
多个并发多线程使用 ServiceLoader 类的实例是不安全的。
感觉大致与java相同,只不过换了方法(SpringFactoriesLoader.loadFactories)
可以拓展SpringBoot的自动装配
可以按需加载,通过名字去文件里面找到对应的实现类全限定名然后加载实例化
支持 AOP、IOC (URL、@SPI、@Adaptive)
自适应扩展机制
调用 ExtensionLoader.getExtensionLoader() 获取接口对应的拓展点加载器,先从缓存中获取,如果没有就通过构造函数创建
调用 extensionLoader.getExtension() 获取对应实现类的实例,先从缓存中获取,如果没有就通过 双重检测 的方式调用 createExtension() 创建实例
通过getExtensionClasses(),先从缓存中获取实现类,如果没有则加载目录下所有的扩展点实现类,再通过ClassLoader加载并放入缓存中,根据name获取到对应的扩展点实现类;通过 loadClass() 实现缓存操作,分别有 Adptive 拓展点放入、extensionClasses 普通实现类放入、cachedWrapperClasses AOP类放入。
通过 injectExtension(instance),IOC,依赖注入只能通过set方法注入,并获取依赖类的类型、名字,通过objectFactory.getExtension() 来创建依赖对象,执行注入依赖;
通过 WrapperClasses,AOP,通过 getExtensionClasses() 读取到的 AOP 代理类,存放在cachedWrapperClasses中,通过获取代理实例进行依赖注入。
通过 ExtensionLoader.getExtensionLoader() 获取接口对应的拓展点加载器
通过 extensionLoader.getExtension() 获取对应实现类的实例
ExtensionLoader.getExtensionLoader()
从缓存中获取接口对应的拓展点加载器 ,如果没有就会通过构造函数创建,并且放到一个ConcurrentHashMap缓存中;
从缓存中获取:EXTENSION_LOADERS.get(type);
通过构造函数创建并存入缓存中:EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
public static <T > ExtensionLoader <T > getExtensionLoader (Class <T > type ) {
// 判断传入的类是否为空、接口、被@SPI注解修饰
if (type == null )
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 @" + SPI .class .getSimpleName () + " Annotation!" );
}
// 从缓存中获取扩展点加载器、如果没有创建对应的加载器并返回
ExtensionLoader <T > loader = (ExtensionLoader <T >) EXTENSION_LOADERS .get (type );
if (loader == null ) {
EXTENSION_LOADERS .putIfAbsent (type , new ExtensionLoader <T >(type ));
loader = (ExtensionLoader <T >) EXTENSION_LOADERS .get (type );
}
return loader ;
}
new ExtensionLoader(type)
private ExtensionLoader (Class <?> type ) {
this .type = type ;
objectFactory = (type == ExtensionFactory .class ? null : ExtensionLoader .getExtensionLoader (ExtensionFactory .class ).getAdaptiveExtension ());
}
extensionLoader.getExtension()
通过缓存获取目标实现类的实例 ,如果没有,会通过双重检查的方式调用 createExtension() 方法创建实例
final域指令重排
单例模式
private final ConcurrentMap <String , Holder <Object >> cachedInstances = new ConcurrentHashMap <String , Holder <Object >>();
public T getExtension (String name ) {
if (name == null || name .length () == 0 )
throw new IllegalArgumentException ("Extension name == null" );
// 获取默认的实体类名字,@SPI注解里面的value属性就是默认
if ("true" .equals (name )) {
return getDefaultExtension ();
}
// 从缓存中获取持有目标对象,没有则创建
Holder <Object > holder = cachedInstances .get (name );
if (holder == null ) {
cachedInstances .putIfAbsent (name , new Holder <Object >());
holder = cachedInstances .get (name );
}
// 单例模式、DCL双重检测
Object instance = holder .get ();
if (instance == null ) {
synchronized (holder ) {
instance = holder .get ();
if (instance == null ) {
// 实例对象
instance = createExtension (name );
holder .set (instance );
}
}
}
return (T ) instance ;
}
通过 getExtensionClasses() 获取对应的实现类
从缓存中获取实例,如果没有通过反射创建实例
调用 injectExtension() 实现 setter 依赖注入
wrapperClasses 包装类实现 AOP
private T createExtension (String name ) {
// 获取扩展点对应的类(通过读取文件里面所有的实现类名字,用ClassLoader加载具体的实现类)
Class <?> clazz = getExtensionClasses ().get (name );
if (clazz == null ) {
throw findException (name );
}
try {
// 从缓存中获取实例,如果没有通过反射创建实例
T instance = (T ) EXTENSION_INSTANCES .get (clazz );
if (instance == null ) {
EXTENSION_INSTANCES .putIfAbsent (clazz , clazz .newInstance ());
instance = (T ) EXTENSION_INSTANCES .get (clazz );
}
// setter 依赖注入 IOC
injectExtension (instance );
// AOP
Set <Class <?>> wrapperClasses = cachedWrapperClasses ;
if (wrapperClasses != null && !wrapperClasses .isEmpty ()) {
for (Class <?> wrapperClass : wrapperClasses ) {
instance = injectExtension ((T ) wrapperClass .getConstructor (type ).newInstance (instance ));
}
}
return instance ;
}
·················
先从缓存中获取实现类,如果没有调用 loadExtensionClasses() 创建并存放到缓存中
private Map <String , Class <?>> getExtensionClasses () {
Map <String , Class <?>> classes = cachedClasses .get ();
if (classes == null ) {
synchronized (cachedClasses ) {
classes = cachedClasses .get ();
if (classes == null ) {
classes = loadExtensionClasses ();
cachedClasses .set (classes );
}
}
}
return classes ;
}
private Map <String , Class <?>> loadExtensionClasses () {
final SPI defaultAnnotation = type .getAnnotation (SPI .class );
·············
Map <String , Class <?>> extensionClasses = new HashMap <String , Class <?>>();
// 从三个目录里面查找
// META-INF/services、META-INF/dubbo、META-INF/dubbo/internal
loadDirectory (extensionClasses , DUBBO_INTERNAL_DIRECTORY );
loadDirectory (extensionClasses , DUBBO_DIRECTORY );
loadDirectory (extensionClasses , SERVICES_DIRECTORY );
return extensionClasses ;
}
根据类名和指定的目录,找到文件获取所有资源,然后一个一个去加载类
再通过 loadClass() 做三种缓存操作,缓存 Adaptive 、WrapperClass 和普通类这三种
private void loadDirectory (Map <String , Class <?>> extensionClasses , String dir ) {
// 获取目录
String fileName = dir + type .getName ();
try {
// 通过目录获取资源
Enumeration <java .net .URL > urls ;
ClassLoader classLoader = findClassLoader ();
if (classLoader != null ) {
urls = classLoader .getResources (fileName );
} else {
urls = ClassLoader .getSystemResources (fileName );
}
// 遍历资源,调用loadResource一个一个加载
if (urls != null ) {
while (urls .hasMoreElements ()) {
java .net .URL resourceURL = urls .nextElement ();
loadResource (extensionClasses , classLoader , resourceURL );
}
}
}
······················
}
private void loadClass (Map <String , Class <?>> extensionClasses , java .net .URL resourceURL , Class <?> clazz , String name ) throws NoSuchMethodException {
·····························
// 如果类标注了 Adptive注解,保存
if (clazz .isAnnotationPresent (Adaptive .class )) {
if (cachedAdaptiveClass == null ) {
cachedAdaptiveClass = clazz ;
} else if (!cachedAdaptiveClass .equals (clazz )) {
throw ···············
}
// 如果是包装类注解, 保存
} else if (isWrapperClass (clazz )) {
Set <Class <?>> wrappers = cachedWrapperClasses ;
if (wrappers == null ) {
cachedWrapperClasses = new ConcurrentHashSet <Class <?>>();
wrappers = cachedWrapperClasses ;
}
wrappers .add (clazz );
} else {
// 普通类进入
clazz .getConstructor ();
······················
String [] names = NAME_SEPARATOR .split (name );
if (names != null && names .length > 0 ) {
Activate activate = clazz .getAnnotation (Activate .class );
if (activate != null ) {
// 标记Adptive 注解,保存
cachedActivates .put (names [0 ], activate );
}
for (String n : names ) {
if (!cachedNames .containsKey (clazz )) {
// 记录映射(类 --> 名字)
cachedNames .put (clazz , n );
}
Class <?> c = extensionClasses .get (n );
if (c == null ) {
// 记录映射(名字 --> 类)
extensionClasses .put (n , clazz );
}
··························
}
}
}
}
依赖注入只能通过set方法注入,并获取依赖类的类型、名字
通过 objectFactory.getExtension() 获取依赖对象
通过 method.invoke() 执行set方法注入依赖
private T injectExtension (T instance ) {
try {
if (objectFactory != null ) {
for (Method method : instance .getClass ().getMethods ()) {
// 说明只能是set注入 并且方法仅有一个参数,且方法访问级别为 public
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 ) : "" ;
// 将获取到的依赖的类,重新执行一遍流程getExtensionLoader()、getAdaptiveExtension()
Object object = objectFactory .getExtension (pt , property );
if (object != null ) {
method .invoke (instance , object );
}
}
······························
return instance ;
}
通过 getExtensionClasses() 读取到的 AOP 代理类,存放在cachedWrapperClasses中
获取代理实例进行依赖注入
// cachedWrapperClasses是getExtensionClasses读取到的AOP代理类,存放在cachedWrapperClasses中
Set <Class <?>> wrapperClasses = cachedWrapperClasses ;
if (wrapperClasses != null && !wrapperClasses .isEmpty ()) {
for (Class <?> wrapperClass : wrapperClasses ) {
// 获取代理类的实例,并进行依赖注入
instance = injectExtension ((T ) wrapperClass .getConstructor (type ).newInstance (instance ));
}
}
return instance ;