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

进入网站wordpress配置网站建设与管理需要什么软件有哪些方面

进入网站wordpress配置,网站建设与管理需要什么软件有哪些方面,哈尔滨视频剪辑培训机构,项目计划Dubbo中的SPI机制 概述 Service Provider Interface 即 SPI#xff0c;是JDK内置的一种服务提供发现机制#xff0c;可以用来启用框架扩展和替换组件。可以让不同的厂商针对统一接口编写不同的实现 SPI实际上是“接口策略模式配置文件”实现的动态加载机制。在系统设计中是JDK内置的一种服务提供发现机制可以用来启用框架扩展和替换组件。可以让不同的厂商针对统一接口编写不同的实现 SPI实际上是“接口策略模式配置文件”实现的动态加载机制。在系统设计中模块之间通常基于接口编程不直接显示指定实现类。一旦代码里指定了实现类就无法在不修改代码的情况下替换为另一种实现。为了达到动态可插拔的效果java提供了SPI以实现服务发现。 SPI机制的应用场景有很多我们比较常用的就是JDBCDubbo等 在谈Dubbo的SPI机制前我们需要先了解一下Java原生的SPI机制 Java原生的SPI 首先我我们先创建一个接口接口中定义一个方法package cuit.epoch.pymjl.spi;/*** author Pymjl* version 1.0* date 2022/5/2 17:43**/ public interface Animal {/*** 动物叫*/void call(); }然后我们分别写两个不同的实现类实现这个接口package cuit.epoch.pymjl.spi.impl;import cuit.epoch.pymjl.spi.Animal;/*** author Pymjl* version 1.0* date 2022/5/2 17:44**/ public class Cat implements Animal {Overridepublic void call() {System.out.println(猫叫喵喵喵~);} } package cuit.epoch.pymjl.spi.impl;import cuit.epoch.pymjl.spi.Animal;/*** author Pymjl* version 1.0* date 2022/5/2 17:45**/ public class Dog implements Animal {Overridepublic void call() {System.out.println(狗叫汪汪汪~);} } 在项目./resources/META-INF/servcie下创建一个文件。文件名为你要动态扩展的接口的全限定名称我们这里就是Animaal接口的全限定名称如图所示文件里面的内容就是实现类的全限定名称 cuit.epoch.pymjl.spi.impl.Cat cuit.epoch.pymjl.spi.impl.Dog编写测试类package cuit.epoch.pymjl.spi;import lombok.extern.slf4j.Slf4j;import java.util.Iterator; import java.util.ServiceLoader;/*** author Pymjl* version 1.0* date 2022/5/2 17:47**/ Slf4j public class Main {public static void main(String[] args) {log.info(这是Java原生的SPI机制);ServiceLoaderAnimal serviceLoader ServiceLoader.load(Animal.class);for (Animal animal : serviceLoader) {animal.call();}} } 运行测试通过测试代码可见我们实现的两个类成功的被加载并运行了相关的方法。但是我们并没有在代码中显示的创建某个实现类我们可以通过这种插件化的配置文件的形式实例化我们想要的对象。将程序的决定权解耦到配置文件中 但是Java原生的SPI也有其不足 通过测试代码我们可知我们并不能直接指定加载某一个我们想要的类只能通过遍历加载配置文件中所有类来找到我们想要的类这样效率是很低的造成资源的浪费获取类的方式不够灵活只能通过Iterator 形式获取不能根据某个参数来获取对应的实现类。ServiceLoader线程不安全针对以上不足我们可以选择Dubbo的SPI机制以此来规避不足 Dubbo的SPI Dubbo 并未使用 Java SPI而是重新实现了一套功能更强的 SPI 机制。Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中通过 ExtensionLoader我们可以加载指定的实现类。 另外Dubbo是通过键值对的方式进行配置我们可以直接通过Key获取我们想要加载的实体类。Dubbo默认的配置文件路径是在./resources/META-INF/dubbo下 编写测试方法 package cuit.epoch.pymjl.spi;import lombok.extern.slf4j.Slf4j;import java.util.Iterator; import java.util.ServiceLoader;/*** author Pymjl* version 1.0* date 2022/5/2 17:47**/ Slf4j public class Main {public static void main(String[] args) {log.info(这是Dubbo的SPI机制);Animal cat ExtensionLoader.getExtensionLoader(Animal.class).getExtension(cat);Animal dog ExtensionLoader.getExtensionLoader(Animal.class).getExtension(dog);cat.call();dog.call();} } 更改配置文件 catcuit.epoch.pymjl.spi.impl.Cat dogcuit.epoch.pymjl.spi.impl.Dog运行测试 通过代码可知Dubbo的SPI机制可直接通过Key获取我们想要的对象实例比原生的Java SPI更有优势除此之外Dubbo在设计中还用到了大量的全局缓存提高了我们实例化对象的效率同时还支持通过注解默认实现AOP,IOC等功能 下面是仿造Dubbo的源码自定义实现的SPI机制的代码来自于Guide哥开源的RPC项目。虽然和源码的有一些差别也没有Dubbo的功能完善但核心思想还是一样的 仿造源码自定义实现Dubbo SPI机制 自定义注解MySpi 通过上文可知Dubbo的SPI机制还要根据spi注解实现对需要扩展的接口做一个标记所以我们先自定义一个注解用来标记我们想要扩展的接口 package cuit.epoch.pymjl.spi;import java.lang.annotation.*;/*** 标记接口声明该接口是一个扩展点** author Pymjl* version 1.0* date 2022/5/3 12:05**/ Documented Retention(RetentionPolicy.RUNTIME) Target(ElementType.TYPE) public interface MySpi {//TODO value可以提供对默认实现的支持但是这方面的切面并没有写只是写在这儿表示有这个东西String value() default ; } Holder对象 顾名思义Holder就是持有通过ExtensionLoader加载来的实例化对象的对象 package cuit.epoch.pymjl.spi;/*** 持有人** author Pymjl* version 1.0* date 2022/5/3 15:11**/ public class HolderT {private volatile T value;public T get() {return value;}public void set(T value) {this.value value;} } ExtensionLoader Dubbo SPI机制的核心类使用它从文件中读取配置并通过反射实例化对象 package cuit.epoch.pymjl.spi;import lombok.extern.slf4j.Slf4j;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap;/*** 模仿Dubbo自定义扩展机制** author Pymjl* version 1.0* date 2022/5/3 15:12**/ Slf4j public class ExtensionLoaderT {/*** SPI配置文件根目录*/private static final String SERVICE_DIRECTORY META-INF/diy-rpc/;/*** 本地缓存Dubbo会先通过getExtensionLoader方法从缓存中获取一个ExtensionLoader* 若缓存未命中则会生成一个新的实例*/private static final MapClass?, ExtensionLoader? EXTENSION_LOADER_MAP new ConcurrentHashMap();/*** 目标扩展类的字节码和实例对象*/private static final MapClass?, Object EXTENSION_INSTANCES new ConcurrentHashMap();/*** 需要加载的扩展类类别*/private final Class? type;/*** 本地缓存*/private final MapString, HolderObject cachedInstances new ConcurrentHashMap();/*** 扩展类实例对象key为配置文件中的keyvalue为实例对象的全限定名称*/private final HolderMapString, Class? cachedClasses new Holder();public ExtensionLoader(Class? type) {this.type type;}/*** 得到扩展加载程序** param type 要扩展的接口必须被MySpi标记* return {code ExtensionLoaderS}*/public static S ExtensionLoaderS getExtensionLoader(ClassS type) {//判断type是否为nullif (type null) {throw new IllegalArgumentException(Extension type should not be null.);}//如果不是接口if (!type.isInterface()) {throw new IllegalArgumentException(Extension type must be an interface.);}//判断是否被MySpi标记if (type.getAnnotation(MySpi.class) null) {throw new IllegalArgumentException(Extension type must be annotated by MySpi);}//先从缓存中获取扩展加载器如果未命中则创建ExtensionLoaderS extensionLoader (ExtensionLoaderS) EXTENSION_LOADER_MAP.get(type);if (extensionLoader null) {//未命中则创建并放入缓存EXTENSION_LOADER_MAP.putIfAbsent(type, new ExtensionLoader(type));extensionLoader (ExtensionLoaderS) EXTENSION_LOADER_MAP.get(type);}return extensionLoader;}/*** 得到扩展类对象实例** param name 配置名字* return {code T}*/public T getExtension(String name) {//检查参数if (name null || name.trim().length() 0) {throw new IllegalArgumentException(Extension name should not be null or empty.);}//先从缓存中获取如果未命中新建HolderObject holder cachedInstances.get(name);if (holder null) {cachedInstances.putIfAbsent(name, new Holder());holder cachedInstances.get(name);}//如果Holder还未持有目标对象则为其创建一个单例对象Object instance holder.get();if (instance null) {synchronized (holder) {instance holder.get();if (instance null) {instance createExtension(name);holder.set(instance);}}}return (T) instance;}/*** 通过扩展类字节码创建实例对象** param name 名字* return {code T}*/private T createExtension(String name) {//从文件中加载所有类型为 T 的扩展类并按名称获取特定的扩展类Class? clazz getExtensionClasses().get(name);if (clazz null) {throw new RuntimeException(No such extension of name name);}T instance (T) EXTENSION_INSTANCES.get(clazz);if (instance null) {try {EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());instance (T) EXTENSION_INSTANCES.get(clazz);} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();log.error(e.getMessage());}}return instance;}/*** 获取所有扩展类** return {code MapString, Class?}*/private MapString, Class? getExtensionClasses() {//从缓存中获取已经加载的扩展类MapString, Class? classes cachedClasses.get();//双重检查if (classes null) {synchronized (cachedClasses) {classes cachedClasses.get();if (classes null) {classes new HashMap();//从配置文件中加载所有扩展类loadDirectory(classes);cachedClasses.set(classes);}}}return classes;}/*** 从配置目录中加载所有扩展类** param extensionsClasses 扩展类的K,V键值对*/private void loadDirectory(MapString, Class? extensionsClasses) {String fileName ExtensionLoader.SERVICE_DIRECTORY type.getName();try {//获取配置文件的资源路径EnumerationURL urls;ClassLoader classLoader ExtensionLoader.class.getClassLoader();urls classLoader.getResources(fileName);if (urls ! null) {while (urls.hasMoreElements()) {URL resourceUrl urls.nextElement();loadResource(extensionsClasses, classLoader, resourceUrl);}}} catch (IOException e) {log.error(e.getMessage());}}/*** 通过Url加载资源** param extensionClasses 扩展类key为配置文件中的keyValue为实现类的全限定名称* param classLoader 类加载器* param resourceUrl 资源url*/private void loadResource(MapString, Class? extensionClasses, ClassLoader classLoader, URL resourceUrl) {try (BufferedReader reader new BufferedReader(new InputStreamReader(resourceUrl.openStream(), StandardCharsets.UTF_8))) {String line;//读取文件中的每一行数据while ((line reader.readLine()) ! null) {//先排除配置文件中的注释final int noteIndex line.indexOf(#);//我们应该忽略掉注释后的内容if (noteIndex 0) {line line.substring(0, noteIndex);}line line.trim();if (line.length() 0) {try {final int keyIndex line.indexOf();String key line.substring(0, keyIndex).trim();String value line.substring(keyIndex 1).trim();if (key.length() 0 value.length() 0) {Class? clazz classLoader.loadClass(value);extensionClasses.put(key, clazz);}} catch (ClassNotFoundException e) {e.printStackTrace();log.error(e.getMessage());}}}} catch (IOException e) {e.printStackTrace();log.error(e.getMessage());}} } 先声明了一些常量例如配置文件的根目录本地缓存等 /*** SPI配置文件根目录*/private static final String SERVICE_DIRECTORY META-INF/diy-rpc/;/*** 本地缓存Dubbo会先通过getExtensionLoader方法从缓存中获取一个ExtensionLoader* 若缓存未命中则会生成一个新的实例*/private static final MapClass?, ExtensionLoader? EXTENSION_LOADER_MAP new ConcurrentHashMap();/*** 目标扩展类的字节码和实例对象*/private static final MapClass?, Object EXTENSION_INSTANCES new ConcurrentHashMap();/*** 需要加载的扩展类类别*/private final Class? type;/*** 本地缓存*/private final MapString, HolderObject cachedInstances new ConcurrentHashMap();/*** 扩展类实例对象key为配置文件中的keyvalue为实例对象的全限定名称*/private final HolderMapString, Class? cachedClasses new Holder();ExtensionLoader 的getExtensionLoader 方法先从缓存中获取一个ExtensionLoader 实例若缓存未命中则new一个。 /*** 得到扩展加载程序** param type 要扩展的接口必须被MySpi标记* return {code ExtensionLoaderS}*/public static S ExtensionLoaderS getExtensionLoader(ClassS type) {//判断type是否为nullif (type null) {throw new IllegalArgumentException(Extension type should not be null.);}//如果不是接口if (!type.isInterface()) {throw new IllegalArgumentException(Extension type must be an interface.);}//判断是否被MySpi标记if (type.getAnnotation(MySpi.class) null) {throw new IllegalArgumentException(Extension type must be annotated by MySpi);}//先从缓存中获取扩展加载器如果未命中则创建ExtensionLoaderS extensionLoader (ExtensionLoaderS) EXTENSION_LOADER_MAP.get(type);if (extensionLoader null) {//未命中则创建并放入缓存EXTENSION_LOADER_MAP.putIfAbsent(type, new ExtensionLoader(type));extensionLoader (ExtensionLoaderS) EXTENSION_LOADER_MAP.get(type);}return extensionLoader;}然后再通过ExtensionLoader 的getExtension 方法获取拓展类对象。跟上面的逻辑一样先从缓存中查找若缓存未命中则新建一个 /*** 得到扩展类对象实例** param name 配置名字* return {code T}*/public T getExtension(String name) {//检查参数if (name null || name.trim().length() 0) {throw new IllegalArgumentException(Extension name should not be null or empty.);}//先从缓存中获取如果未命中新建HolderObject holder cachedInstances.get(name);if (holder null) {cachedInstances.putIfAbsent(name, new Holder());holder cachedInstances.get(name);}//如果Holder还未持有目标对象则为其创建一个单例对象Object instance holder.get();if (instance null) {synchronized (holder) {instance holder.get();if (instance null) {instance createExtension(name);holder.set(instance);}}}return (T) instance;}/*** 通过扩展类字节码创建实例对象** param name 名字* return {code T}*/private T createExtension(String name) {//从文件中加载所有类型为 T 的扩展类并按名称获取特定的扩展类Class? clazz getExtensionClasses().get(name);if (clazz null) {throw new RuntimeException(No such extension of name name);}T instance (T) EXTENSION_INSTANCES.get(clazz);if (instance null) {try {EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());instance (T) EXTENSION_INSTANCES.get(clazz);} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();log.error(e.getMessage());}}return instance;}/*** 获取所有扩展类** return {code MapString, Class?}*/private MapString, Class? getExtensionClasses() {//从缓存中获取已经加载的扩展类MapString, Class? classes cachedClasses.get();//双重检查if (classes null) {synchronized (cachedClasses) {classes cachedClasses.get();if (classes null) {classes new HashMap();//从配置文件中加载所有扩展类loadDirectory(classes);cachedClasses.set(classes);}}}return classes;}/*** 从配置文件中加载所有扩展实现类** param extensionsClasses 扩展类的K,V键值对*/private void loadDirectory(MapString, Class? extensionsClasses) {String fileName ExtensionLoader.SERVICE_DIRECTORY type.getName();try {//获取配置文件的资源路径EnumerationURL urls;ClassLoader classLoader ExtensionLoader.class.getClassLoader();urls classLoader.getResources(fileName);if (urls ! null) {while (urls.hasMoreElements()) {URL resourceUrl urls.nextElement();loadResource(extensionsClasses, classLoader, resourceUrl);}}} catch (IOException e) {log.error(e.getMessage());}}/*** 通过Url加载资源** param extensionClasses 扩展类key为配置文件中的keyValue为实现类的全限定名称* param classLoader 类加载器* param resourceUrl 资源url*/private void loadResource(MapString, Class? extensionClasses, ClassLoader classLoader, URL resourceUrl) {try (BufferedReader reader new BufferedReader(new InputStreamReader(resourceUrl.openStream(), StandardCharsets.UTF_8))) {String line;//读取文件中的每一行数据while ((line reader.readLine()) ! null) {//先排除配置文件中的注释final int noteIndex line.indexOf(#);//我们应该忽略掉注释后的内容if (noteIndex 0) {line line.substring(0, noteIndex);}line line.trim();if (line.length() 0) {try {final int keyIndex line.indexOf();String key line.substring(0, keyIndex).trim();String value line.substring(keyIndex 1).trim();if (key.length() 0 value.length() 0) {Class? clazz classLoader.loadClass(value);extensionClasses.put(key, clazz);}} catch (ClassNotFoundException e) {e.printStackTrace();log.error(e.getMessage());}}}} catch (IOException e) {e.printStackTrace();log.error(e.getMessage());}}--------------------- 作者Pymj 来源CSDN 原文https://blog.csdn.net/apple_52109766/article/details/124577928 版权声明本文为作者原创文章转载请附上博文链接 内容解析ByCSDN,CNBLOG博客文章一键转载插件
http://www.huolong8.cn/news/435259/

相关文章:

  • 做兼职的网站都有哪些工作影视公司宣传片
  • 怎样跟网站做优化呢店面设计有哪些
  • 女装店网站源码徐州手机模板建站
  • 做网站美工音乐网站开发工具
  • ins做甜品网站申请网站建设费
  • 如何设置网站标题用什么软件做网站hao
  • 网站建设需要钱吗wordpress最新博客主题
  • 关于数据机房建设的网站制作网站的页面设计怎么做
  • 网站注入木马哈尔滨优化调整人员流动管理
  • 快速一体化网站建设网站建设中一般要多久
  • 王野天照片广东网站营销seo费用
  • 建设厅网站上人员怎么导出中简风格wordpress主题
  • 屏蔽ip地址访问网站如何给网站做下载附件
  • 网站开发的软件学影视后期的正规学校
  • 做国外销售都上什么网站wordpress文章类型查询
  • 做网站需要学习什么知识温州地区做网站
  • 热门课程自己做网站沈阳广告设计公司
  • 家装效果图网站菜单设计制作图片
  • 能搜任何网站的浏览器网站制作公司商丘市
  • 平台网站建设推荐免费金融网站模板
  • 学生网站作品前端做网站框架
  • 做网站导航一般字号是多少网站技术策划内容
  • 网站后台上次图片做a图片网站
  • 网站开发与数据库江苏网站建设制作
  • 重庆网上房地产网站网站建设费用入账
  • 2016广州网站设计公司在局域网服务器建设网站教程
  • 网站毕业设计任务书营销型网站建设与网页设计
  • 网站搜索不出来福田网站制作设计
  • 合肥网页网站制作做那个网站销售产品比较好
  • 网站怎样多语言wordpress银行模板