zl程序教程

您现在的位置是:首页 >  后端

当前栏目

ServiceLoader服务提供者模式,实现动态插件加载,类责任链模式

模式插件 实现 动态 加载 责任
2023-09-14 08:58:00 时间
ServiceLoader的功能比ClassLoader简单,它可以帮我们获取所有实现了某接口或基类的类。当然前提是ClassLoader已经加载过的类。举个例子:
定义一个接口:

public interface IService { 

 public String sayHello(); 

 public String getScheme(); 

以及两个实现类:

public class HDFSService implements IService { 

 @Override 

 public String sayHello() { 

 return "Hello HDFS!!"; 

 @Override 

 public String getScheme() { 

 return "hdfs"; 

public class LocalService implements IService { 

 @Override 

 public String sayHello() { 

 return "Hello Local!!"; 

 @Override 

 public String getScheme() { 

 return "local"; 

将 HDFSService 和 LocalService 打包成 jar,java包的 META-INFO/services 下以IService这个类的全名来新建立一个文件,文件中的内容为两个实现类的全名:

org.hadoop.java.HDFSService
org.hadoop.java.LocalService

我们通过一下方式来调用对应的实现类:

public class ServiceLoaderTest { 

 public static void main(String[] args) { 

 //need to define related class full name in /META-INF/services/.... 

 ServiceLoader IService serviceLoader = ServiceLoader 

 .load(IService.class); 

 for (IService service : serviceLoader) { 

 System.out.println(service.getScheme()+"="+service.sayHello()); 

Netbean的插件就是使用ServiceLoader动态加载。先用类加载器将新的插件jar包加载到JVM,然后就可以使用ServiceLoader调用。

类责任链模式 有时候我们的程序需要根据匹配的条件,执行某段代码,如:

if (optionA) {

 if (optionB) {

 doSomething1();

 } else {

 doSomething2();

} else {

 doSomething3();

直接用if else条件判断,比较复杂,不好维护。
类似上面的代码,根据不同的输入选项或命令行参数等调用不同的方法来完成某些操作,而不是单纯的返回数据。因此,这些选项是为了确定现在这个request是谁的职责,而这正是“责任链模式”要解决的问题!本节的标题为“类责任链模式”,表示我的解决方案是类似“责任链模式”,并不严格和它保持一致,但核心思想是一致的:使多个对象都有机会处理请求。

因此,每个RequestHandler都需提供一个接口判断自己能否处理当前请求;如果能处理,则Client调用另一个执行的接口:

public interface Handler {

 public boolean accept(Properties options);

 public void execute();

于是,上面的分支结构对应三个独立的Handler类:

public class RequestHandler1 implements Handler {

 public boolean accept(Properties options) {

 return options.getProperty("A") != null

 options.getProperty("B") != null;

 public void execute() {

 doSomething1();

public class RequestHandler2 implements Handler {

 public boolean accept(Properties options) {

 return options.getProperty("A") != null

 options.getProperty("B") == null;

 public void execute() {

 doSomething2();

public class RequestHandler3 implements Handler {

 public boolean accept(Properties options) {

 return options.getProperty("A") == null;

 public void execute() {

 doSomething3();

接下来还需要一个额外的管理类负责这些类的实例化的请求的分发:

import java.util.ServiceLoader;

import java.util.Iterator;

public class Manager {

 private static Arraylist;

 static {

 list = new Array();

 ServiceLoaderloader = ServiceLoader.load(Handler.class);

 Iteratorit = loader.iterator();

 while (it.hasNext()) {

 list.add(it.next());

 public static void process(Properties options) {

 for (Handler handler : list) {

 if (handler.accept(options)) {

 handler.execute();

上面代码使用了服务加载功能自动实例化所有注册过的Handler子类,如果你还不了解它的原理,可查看相应的API文档。有了这些代码,已经万事具备!也许你已经发现,这样的设计和JDBC的接口不谋而合:Manager对应java.sql.DriverManager、Handler对应java.sql.Driver、RequestHandler这些类则对应数据库厂商自己实现的驱动程序。

基于这样的框架,它的代码总量也许比原来的要多,但你不再需要在一堆if else中仔细推敲代码执行的前提条件,所有的前提条件都在accept函数里;添加新的功能所要做的仅需实现一个新的类,无须修改现有代码,符合开闭原则。

Reference 类责任链模式
转一篇很不错的介绍NetBeans的文章
http://blog.csdn.net/kokojhuang/article/details/8273303


利用springboot初始化机制三种实现策略模式的应用 面试时总被问,spring中使用了哪些设计模式,你在实际开发中又使用哪些设计模式。给他手指一个方向跟他说,这就是一个模式:go out!。
读源码长知识 | 动态扩展类并绑定生命周期的新方式 在阅读viewModelScope源码时,发现了一种新的方式。 协程需隶属于某 CoroutineScope ,以实现structured-concurrency,而 CoroutineScope 应
(十八) 反射的原理是什么,反射创建类实例的三种方式是什么? javac在这一阶段会把java代码编译为class文件,保存在硬盘中,这个文件中保存着这个类的类名、成员名、构造方法、其他方法等。
Spring解析,加载及实例化Bean的顺序(零配置) 在A之前实例化好。很多时候Spring智能地为我们做好了这些工作,但某些情况下可能不是,比如Springboot的@AutoConfigureAfter注解,