1、双亲委派机制
1.1 定义
当一个类加载器收到了类加载的请求的时候,他不会直接去加载指定的类,而是把这个请求委托给自己的父加载器去加载。
如果父类为空,交给bootstrap classloader 加载。
如果类还是无法被加载到,则触发findclass,抛出classNotFoundException(findclass这个方法当前只有一个语句,就是抛出classNotFoundException),如果想自己实现类加载器的话,可以继承classLoader后重写findclass方法,加载对应的类)
1.2优点
避免类的重复加载
保护程序安全,防止核心API被随意篡改
2、SPI(service provider interface)定义:
SPI是jdk内置的一种服务提供发现机制。可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如java.sql.Driver接口,常用的关系型数据有Mysql、Oracle、SQLServer、DB2等,这些不同类型的数据库使用的驱动程序各不相同,那JDK不可能把所有厂商的驱动都实现,只能制定一个标准接口,其他不同厂商可以针对同一接口做出不同的实现,各个数据库厂商根据标准来实现自己的驱动,这就是SPI机制。
下面看下Mysql的Driver,以com.mysql.cj.jdbc.Driver 为例
META-INF目录的作用是相当于信息包,用来配置应用程序、扩展程序、类加载器和服务manifest.mf文件,在打包时自动生成。
其中manifest.mf里面描述了程序的基本信息、Main-Class
的入口、jar
依赖路径Class-Path
而META-INFO/services 的作用是实现接口循环实现类的功能, 除了jdbc模块的方案(Driver)之外,还有日志模块的方案(l4j),xml解析模块等。
回到正题:
com.mysql.cj.jdbc.Driver的源码需要往DriverManager进行注册
最终如下图所示,需要往 registeredDrivers 里面进行添加
而registeredDrivers 变量在 DriverManager 静态初始化的时候会进行调用把真实的类进行加载出来
例子
创建一个 interface 接口
package com.zhianchen.mysqlremark.springboottest.spi; /* * *@Description TODO *@Author chenzhian *@Date 2022/10/21 11:25 */ public interface UserService { void login(); }
实现
package com.zhianchen.mysqlremark.springboottest.spi.Impl; import com.zhianchen.mysqlremark.springboottest.spi.UserService; /* * *@Description TODO *@Author chenzhian *@Date 2022/10/21 11:26 */ public class AppUserLoginServiceImpl implements UserService { @Override public void login() { System.out.println("AppUserLoginServiceImpl"); } }
package com.zhianchen.mysqlremark.springboottest.spi.Impl; import com.zhianchen.mysqlremark.springboottest.spi.UserService; /* * *@Description TODO *@Author chenzhian *@Date 2022/10/21 11:26 */ public class PCUserLoginServiceImpl implements UserService { @Override public void login() { System.out.println("PCUserLoginServiceImpl"); } }
然后在resources 创建目录 META-INF.services (注意:这里是services 而不是service!!!!!)
创建文件 com.zhianchen.mysqlremark.springboottest.spi.UserService (这里的文件名要对应UserService包)
里面的内容
com.zhianchen.mysqlremark.springboottest.spi.Impl.PCUserLoginServiceImpl com.zhianchen.mysqlremark.springboottest.spi.Impl.AppUserLoginServiceImpl
创建一个Test
/* * *@Description TODO *@Author chenzhian *@Date 2022/10/21 14:02 */ public class SpiTest { public static void main(String[] args) { ServiceLoader<UserService> serviceLoader= ServiceLoader.load(UserService.class); for (UserService userService:serviceLoader ) { userService.login(); } } }
之前的结果是
PCUserLoginServiceImpl
AppUserLoginServiceImpl
参考
纯原创长文-深入理解Java类加载(双亲委派机制及其破坏 JavaSPI和DubboSPI的区别和联系)
面试官:你说你用过Dubbo,那你说说看Dubbo的SPI?
https://www.cnblogs.com/masaike/p/15490402.html
META-INF 作用
标签:java,springboottest,mysqlremark,spi,SPI,UserService,机制,com,加载 From: https://www.cnblogs.com/zhian/p/16813853.html