java spi带参数_Java SPI机制

本文详细介绍了Java SPI机制,包括ServiceProviderInterface的作用、如何通过ServiceLoader动态加载第三方实现,并展示了SPI工作机制和在实际项目中的应用,如数据库驱动加载。要了解如何利用SPI进行框架扩展和组件替换,本文是您的指南。
摘要由CSDN通过智能技术生成

Java SPI机制

什么是SPI

SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。

SPI有什么用

调用者根据实际使用需要,启用、扩展、或者替换框架的实现策略

如:

数据库加载驱动 java.sql.DriverManager

AccessController.doPrivileged(new PrivilegedAction() {

public void run() {

//此处使用JDK的SPI加载机制,加载所有的驱动,即java.sql.Driver接口的实现类

ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class);

Iterator driversIterator = loadedDrivers.iterator();

/* Load these drivers, so that they can be instantiated.

* It may be the case that the driver class may not be there

* i.e. there may be a packaged driver with the service class

* as implementation of java.sql.Driver but the actual class

* may be missing. In that case a java.util.ServiceConfigurationError

* will be thrown at runtime by the VM trying to locate

* and load the service.

*

* Adding a try catch block to catch those runtime errors

* if driver not available in classpath but it's

* packaged as service and that service is there in classpath.

*/

try{

while(driversIterator.hasNext()) {

driversIterator.next();

}

} catch(Throwable t) {

// Do nothing

}

return null;

}

});

println("DriverManager.initialize: jdbc.drivers = " + drivers);

Dubbo

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.TYPE})

public @interface SPI {

/**

* default extension name

*/

String value() default "";

}

SPI工作机制

代码片段 java.util.ServiceLoader

/**

* Creates a new service loader for the given service type, using the

* current thread's {@linkplain java.lang.Thread#getContextClassLoader

* context class loader}.

*

*

An invocation of this convenience method of the form

*

*

 
  

* ServiceLoader.load(service)

*

* is equivalent to

*

*

 
  

* ServiceLoader.load(service,

* Thread.currentThread().getContextClassLoader())

*

* @param the class of the service type

*

* @param service

* The interface or abstract class representing the service

*

* @return A new service loader

*/

public static ServiceLoader load(Class service) {

ClassLoader cl = Thread.currentThread().getContextClassLoader();

return ServiceLoader.load(service, cl);

}

通过调用load方法来实现对象的创建

最终使用Class.forName("class name").newInstance()来创建接口实现

SPI使用

当服务提供者提供了接口的一种具体实现后,在jar包的META-INF/services目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名;

接口实现类所在的jar包放在主程序的classpath中;

主程序通过ServiceLoader.load()动态装载实现模块,它通过扫描META-INF/services目录下的配置文件找到实现类的全限定名,把类加载到JVM;

SPI的实现类必须携带一个不带参数的构造方法;

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值