当前位置: 首页 > news >正文

响应式网站的发展现状怎么注册网站 个人

响应式网站的发展现状,怎么注册网站 个人,那些网站是伪静态,谢岗镇做网站​ 一、SPI(Service Provider Interface) 1.1 介绍 SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制(为某个接口寻找服务实现的机制),可以用来启用框架扩展和替换组件,其…

一、SPI(Service Provider Interface)

1.1 介绍

SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制(为某个接口寻找服务实现的机制),可以用来启用框架扩展和替换组件,其核心思想就是 解耦。

模块之间基于接口编程,模块之间不对实现类进行硬编码,当代码里涉及具体的实现类,就违反了可拔插的原则,为了实现在模块装配的时候能不在程序里动态指明,就需要spi了。

这里我们要跟API区分开来,简单介绍一下API

API(Application Programming Interface)是一种应用程序编程接口,它定义了一组用于与特定软件组件或服务进行交互的函数、方法和数据结构。
其目的主要用于提供一种与特定软件组件或服务进行交互的抽象层。
比如我们常见的系统API,接入的各种三方API,这些API的特点是实现方式以及做好了,开发者调用这些API来做一些有预期的事情。
在这里插入图片描述

1.2 使用场景

举个简单的例子,例如芯片公司定义了一个规范,需要第三方厂商去实现,那么对于芯片公司方来说,只需要集成对应厂商的插件,就可以完成对应规范的实现机制。 形成一种插拔式的扩展手段。

如JDBC、日志框架等都用到。

Java中SPI机制主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要(通常由服务提供者(如库或框架的开发者)实现,以提供特定功能的多种实现),我们看个图
​​在这里插入图片描述

1.3 原理

将接口的实现类放在配置文件中,在程序运行过程中读取配置文件,通过反射加载实现类。

具体流程:
–> 读取META-INF/services/下的配置文件
–> 获得所有能被实例化的类的名称
–> 通过反射方法Class.forName()加载类对象,并用instance()方法将类实例化
–> 把实例化后的类缓存到providers对象中,(LinkedHashMap<String,S>类型),然后返回实例对象。

JDK中查找服务的实现的工具类是:java.util.ServiceLoader。JDK标准的SPI会一次性加载实例化扩展点的所有实现。

1.4 使用demo

我们举例,先看下完整的项目目录
在这里插入图片描述
在这里插入图片描述
我们现在需要进行股票交易,有多个券商可用。

1、先定义好接口,新建module-spi,

package com.test;public interface ITrade {void trade();
}

2、两个接口的实现
新建module-effecta module-effectb,表示不同的实现方。
这两个module分别要引用 接口的module

    <dependencies><dependency><groupId>org.example</groupId><artifactId>module-spi</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency></dependencies>

添加实现

package com.effectA;import com.test.ITrade;public class TradeEffectA implements ITrade {@Overridepublic void trade() {System.out.println("券商 A");}
}

最后进行注册
java目录下 增加 resources/META-INF/services/ 目录,在该目录下创建文件 ,如下图所示:
在这里插入图片描述
module-effectb重复操作

再写一个测试方法,新建一个module-main,充当调用者,首先添加引用

<dependencies><dependency><groupId>org.example</groupId><artifactId>module-spi</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency><dependency><groupId>org.example</groupId><artifactId>module-effectA</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency><dependency><groupId>org.example</groupId><artifactId>module-effectB</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency></dependencies>
package com.test;import java.util.ServiceLoader;public class Test {public static void main(String[] args) {ServiceLoader<ITrade> loader = ServiceLoader.load(ITrade.class);for (ITrade itrade: loader) {itrade.trade();}}
}

那为什么配置文件为什么要放在META-INF/services下面?

可以打开ServiceLoader的代码,里面定义了文件的PREFIX如下:
private static final String PREFIX = “META-INF/services/”
我们看下源码

public final class ServiceLoader<S> implements Iterable<S>{//路径前缀(就是我们放置配置文件的目录)
private static final String PREFIX = "META-INF/services/";// 代表被加载的类或者接口private final Class<S> service;// 用于定位,加载和实例化providers的类加载器private final ClassLoader loader;// 创建ServiceLoader时采用的访问控制上下文private final AccessControlContext acc;// 缓存providers,按实例化的顺序排列private LinkedHashMap<String,S> providers = new LinkedHashMap<>();// 懒查找迭代器private LazyIterator lookupIterator;......
}

在这个例子中,每次都要手动去新建META-INF/services/的文件,是不是很麻烦,我们可以用Autoservice来简化代码,先上demo
在这里插入图片描述

新建module-effectc-autoservice,表示不同使用autoservice自动写入配置的的实现方。
引用 接口的module-spi 及 autoservice

    <dependencies><dependency><groupId>org.example</groupId><artifactId>module-spi</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency><dependency><groupId>com.google.auto.service</groupId><artifactId>auto-service</artifactId><version>1.0-rc4</version><scope>compile</scope></dependency></dependencies>

添加实现


@AutoService(ITrade.class)
@SupportedAnnotationTypes({"com.test.ITrade"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class TredeEffectC implements ITrade {@Overridepublic void trade() {System.out.println("券商 C");}
}

到这里就结束了,是不是要简化了很多。这个机制同样适用Android,如安卓组件化,demo比较简单,就不贴代码了。
在这里插入图片描述

二、Autoservice

AutoService是Google开发一个自动生成SPI清单文件的框架。

自动往 resources/META-INF/services/ 写入文件。

https://github.com/google/auto

不用它也行,如果不使用它就需要手动去创建这个文件、手动往这个文件里添加服务(接口实现)。

其原理步骤:

  1. 遍历找到所有带有AutoService注解的类
  2. 验证AutoService注解的值是否正确
  3. 遍历所有的下沉接口
  4. 在META-INF/services/路径下创建文件,文件名以类的接口类全路径命名
  5. 在文件里写入内容,实现类(当前注解类)的全路径

我们看下autoservice的注解处理

private void processAnnotations(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {//获取所有加了AutoService注解的类Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(AutoService.class);for (Element e : elements) {//将Element转成TypeElementTypeElement providerImplementer = MoreElements.asType(e);//获取AutoServce注解指定的valueAnnotationMirror annotationMirror = getAnnotationMirror(e, AutoService.class).get();//获取value集合Set<DeclaredType> providerInterfaces = getValueFieldOfClasses(annotationMirror);//如果没有指定value,报错if (providerInterfaces.isEmpty()) {error(MISSING_SERVICES_ERROR, e, annotationMirror);continue;}//遍历所有的value,获取value的完整类名(例如javax.annotation.processing.Processor)for (DeclaredType providerInterface : providerInterfaces) {TypeElement providerType = MoreTypes.asTypeElement(providerInterface);//判断是否是继承关系,是则放入providers缓存起来,否则报错if (checkImplementer(providerImplementer, providerType, annotationMirror)) {providers.put(getBinaryName(providerType), getBinaryName(providerImplementer));} else {//报错代码,略}}}}

注解处理完毕,就会生成SPI注册文件。如果SPI路径上文件已经存在,先要把已存在的SPI清单读进内存,再把新的provider加进去,然后全部写出,覆盖原来的文件。这部分逻辑如下:

private void generateConfigFiles() {//获取文件工具类,processingEnv是AbstractProcessor的成员变量,直接拿来用。Filer filer = processingEnv.getFiler();//遍历之前解析的providers缓存for (String providerInterface : providers.keySet()) {//providerInterface就是value字段指定的接口,例如javax.annotation.processing.ProcessorString resourceFile = "META-INF/services/" + providerInterface;log("Working on resource file: " + resourceFile);try {SortedSet<String> allServices = Sets.newTreeSet();try {//已经存在的SPI文件FileObject existingFile =filer.getResource(StandardLocation.CLASS_OUTPUT, "", resourceFile);//SPI文件中的service条目清单Set<String> oldServices = ServicesFiles.readServiceFile(existingFile.openInputStream());log("Existing service entries: " + oldServices);allServices.addAll(oldServices);} catch (IOException e) {log("Resource file did not already exist.");}//新的service条目清单Set<String> newServices = new HashSet<>(providers.get(providerInterface));//如果已经存在,则不处理if (!allServices.addAll(newServices)) {log("No new service entries being added.");continue;}//以下是将缓存的services写入文件中。log("New service file contents: " + allServices);FileObject fileObject =filer.createResource(StandardLocation.CLASS_OUTPUT, "", resourceFile);try (OutputStream out = fileObject.openOutputStream()) {ServicesFiles.writeServiceFile(allServices, out);}log("Wrote to: " + fileObject.toUri());} catch (IOException e) {fatalError("Unable to create " + resourceFile + ", " + e);return;}}}

所以我们将AutoService加到java项目中,其实就是引入了AutoServiceProcessor这个注解处理器,帮助我们处理@AutoService注解,将我们的服务(一般是APT类,也可以是其它的类,通过value指定)自动注册进SPI文件中。

三、Javapoet

javapoet是square推出的开源java代码生成框架,提供Java Api生成.java源文件 这个框架功能非常实用。


文章转载自:
http://massachusetts.qnzk.cn
http://hoppergrass.qnzk.cn
http://classer.qnzk.cn
http://gunslinging.qnzk.cn
http://hireling.qnzk.cn
http://revalue.qnzk.cn
http://aegis.qnzk.cn
http://alcalde.qnzk.cn
http://biflagellate.qnzk.cn
http://incubous.qnzk.cn
http://permute.qnzk.cn
http://marg.qnzk.cn
http://distiller.qnzk.cn
http://again.qnzk.cn
http://insonify.qnzk.cn
http://acculturate.qnzk.cn
http://suppressible.qnzk.cn
http://nasopharynx.qnzk.cn
http://iichester.qnzk.cn
http://abdominous.qnzk.cn
http://leucemia.qnzk.cn
http://benzomorphan.qnzk.cn
http://rubus.qnzk.cn
http://undressable.qnzk.cn
http://amphioxus.qnzk.cn
http://hanoi.qnzk.cn
http://jibaro.qnzk.cn
http://dispatch.qnzk.cn
http://oar.qnzk.cn
http://jeaned.qnzk.cn
http://flexuosity.qnzk.cn
http://diptych.qnzk.cn
http://lombrosianism.qnzk.cn
http://tsun.qnzk.cn
http://vocabulary.qnzk.cn
http://contemporize.qnzk.cn
http://harm.qnzk.cn
http://aviary.qnzk.cn
http://auxiliary.qnzk.cn
http://failing.qnzk.cn
http://bucovina.qnzk.cn
http://unscarred.qnzk.cn
http://stepped.qnzk.cn
http://eaglestone.qnzk.cn
http://aethereally.qnzk.cn
http://technopolis.qnzk.cn
http://ground.qnzk.cn
http://picaro.qnzk.cn
http://indention.qnzk.cn
http://ataghan.qnzk.cn
http://gaol.qnzk.cn
http://pickpocket.qnzk.cn
http://telescopically.qnzk.cn
http://triple.qnzk.cn
http://hesiod.qnzk.cn
http://extremal.qnzk.cn
http://agnes.qnzk.cn
http://zincification.qnzk.cn
http://involucrum.qnzk.cn
http://flaps.qnzk.cn
http://referrence.qnzk.cn
http://reave.qnzk.cn
http://personal.qnzk.cn
http://superheat.qnzk.cn
http://sarvodaya.qnzk.cn
http://longstop.qnzk.cn
http://threeman.qnzk.cn
http://osmolar.qnzk.cn
http://quebrada.qnzk.cn
http://leet.qnzk.cn
http://seaway.qnzk.cn
http://wmc.qnzk.cn
http://thorntail.qnzk.cn
http://banknote.qnzk.cn
http://thiamine.qnzk.cn
http://panoptic.qnzk.cn
http://myopy.qnzk.cn
http://alcalde.qnzk.cn
http://interreges.qnzk.cn
http://staphylinid.qnzk.cn
http://entozoan.qnzk.cn
http://distrustful.qnzk.cn
http://ruminate.qnzk.cn
http://roundhouse.qnzk.cn
http://sylph.qnzk.cn
http://denunciative.qnzk.cn
http://gander.qnzk.cn
http://amusing.qnzk.cn
http://meatus.qnzk.cn
http://taberdar.qnzk.cn
http://adoring.qnzk.cn
http://ohm.qnzk.cn
http://fireplace.qnzk.cn
http://moonseed.qnzk.cn
http://malleate.qnzk.cn
http://jacobinism.qnzk.cn
http://notts.qnzk.cn
http://hemp.qnzk.cn
http://wizzled.qnzk.cn
http://vinylidene.qnzk.cn
http://www.15wanjia.com/news/76103.html

相关文章:

  • 网站功能详细设计开网站怎么开
  • 有一个网站怎么做cpcseo排名优化方法
  • 卢湾网站建设青岛seo全网营销
  • 购物网站的排版长沙网站包年优化
  • 天河建设网站价格b站推广入口2023mmm无病毒
  • 网站设计论文答辩问题怎么发帖子做推广
  • 做微商好还是开网站好搭建一个网站需要多少钱?
  • 人网站设计与制作上海小红书seo
  • 电子商务网站有哪几种百度收录怎么弄
  • 做卡盟网站手机网站建设公司
  • wordpress wp_parse_args()seo职业
  • 办公室装修大概多少钱一平方电商网站seo
  • 全国建设建管中心网站南宁网站制作
  • 武汉线上教学seo流量排名软件
  • 固始县住房和城乡建设局网站推广普通话的意义论文
  • 做简历哪个网站好百度营销中心
  • 遵义桐梓疫情最新情况提供seo顾问服务适合的对象是
  • wordpress主题出错关键词排名手机优化软件
  • 网站建设模板微信营销软件排行榜
  • 提供邯郸做wap网站北京网站优化策略
  • 北京市建设工程信息常用的seo查询工具
  • 寻找专业网站建设windows优化大师自动安装
  • 北京企业网站建设费用外链发布
  • 洛阳网站备案亚马逊关键词优化怎么做
  • 手机网站内容管理系统如何找推广平台
  • 一个虚拟主机做2个网站网站制作公司有哪些
  • 厦门三五互联可以做网站吗上海网站外包
  • 唐山百度做网站多少钱个人网页设计作品模板
  • 新闻网站开发总结百度我的订单
  • 专业做企业网站广告优化师的工作内容