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);
...}
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);
}
原文:https://www.cnblogs.com/leifonlyone/p/12862590.html