2024年最新组件化框架设计之Java SPI机制(三)(1),阿里大牛亲手操刀微服务架构实战

最后

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友

image.png

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

//java.sql.DriverManager.java

//当调用DriverManager.getConnection(…)时,static会在getConnection(…)执行之前被触发执行

/**

  • Load the initial JDBC drivers by checking the System property

  • jdbc.properties and then use the {@code ServiceLoader} mechanism

*/

static {

loadInitialDrivers();

println(“JDBC DriverManager initialized”);

}

2.loadInitialDrivers()中完成了引入的数据库驱动的查找以及载入,本示例只引入了oracle厂商的mysql,我们具体看看。

//java.util.serviceLoader.java

private static void loadInitialDrivers() {

String drivers;

try {

drivers = AccessController.doPrivileged(new PrivilegedAction() {

public String run() {

//使用系统变量方式加载

return System.getProperty(“jdbc.drivers”);

}

});

} catch (Exception ex) {

drivers = null;

}

//如果spi 存在将使用spi方式完成提供的Driver的加载

// If the driver is packaged as a Service Provider, load it.

// Get all the drivers through the classloader

// exposed as a java.sql.Driver.class service.

// ServiceLoader.load() replaces the sun.misc.Providers()

AccessController.doPrivileged(new PrivilegedAction() {

public Void run() {

//查找具体的provider,就是在META-INF/services/***.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);

if (drivers == null || drivers.equals(“”)) {

return;

}

String[] driversList = drivers.split(“:”);

}

}

3.java.util.ServiceLoader 加载spi实现类.

上一步的核心代码如下,我们接着分析:

//java.util.serviceLoader.java

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

Iterator driversIterator = loadedDrivers.iterator();

try{

//查找具体的实现类的全限定名称

while(driversIterator.hasNext()) {

//加载并初始化实现

driversIterator.next();

}

} catch(Throwable t) {

// Do nothing

}

主要是通过ServiceLoader来完成的,我们按照执行顺序来看看ServiceLoader实现:

//初始化一个ServiceLoader,load参数分别是需要加载的接口class对象,当前类加载器

public static ServiceLoader load(Class service) {

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

return ServiceLoader.load(service, cl);

}

public static ServiceLoader load(Class service,

ClassLoader loader)

{

return new ServiceLoader<>(service, loader);

}

遍历所有存在的service实现

public boolean hasNext() {

if (acc == null) {

return hasNextService();

} else {

PrivilegedAction action = new PrivilegedAction() {

public Boolean run() { return hasNextService(); }

};

return AccessController.doPrivileged(action, acc);

}

}

//写死的一个目录

private static final String PREFIX = “META-INF/services/”;

private boolean hasNextService() {

if (nextName != null) {

return true;

}

if (configs == null) {

try {

String fullName = PREFIX + service.getName();

//通过相对路径读取classpath中META-INF目录的文件,也就是读取服务提供者的实现类全限定名

if (loader == null)

configs = ClassLoader.getSystemResources(fullName);

else

configs = loader.getResources(fullName);

} catch (IOException x) {

fail(service, “Error locating configuration files”, x);

}

}

//判断是否读取到实现类全限定名,比如mysql的“com.mysql.jdbc.Driver

while ((pending == null) || !pending.hasNext()) {

if (!configs.hasMoreElements()) {

return false;

}

pending = parse(service, configs.nextElement());

}

nextName = pending.next();//nextName保存,后续初始化实现类使用

return true;//查到了 返回true,接着调用next()

}

public S next() {

if (acc == null) {//用来判断serviceLoader对象是否完成初始化

return nextService();

} else {

PrivilegedAction action = new PrivilegedAction() {

public S run() { return nextService(); }

};

return AccessController.doPrivileged(action, acc);

}

}

private S nextService() {

if (!hasNextService())

throw new NoSuchElementException();

String cn = nextName;//上一步找到的服务实现者全限定名

nextName = null;

Class<?> c = null;

try {

//加载字节码返回class对象.但并不去初始化(换句话就是说不去执行这个类中的static块与static变量初始化)

//

c = Class.forName(cn, false, loader);

} catch (ClassNotFoundException x) {

fail(service,

“Provider " + cn + " not found”);

}

if (!service.isAssignableFrom©) {

fail(service,

“Provider " + cn + " not a subtype”);

}

try {

//初始化这个实现类.将会通过static块的方式触发实现类注册到DriverManager(其中组合了一个CopyOnWriteArrayList的registeredDrivers成员变量)中

S p = service.cast(c.newInstance());

providers.put(cn, p);//本地缓存 (全限定名,实现类对象)

return p;

} catch (Throwable x) {

fail(service,

“Provider " + cn + " could not be instantiated”,

x);

}

throw new Error(); // This cannot happen

}

上一步中,Sp = service.cast(c.newInstance()) 将会导致具体实现者的初始化,比如mysqlJDBC,会触发如下代码:

//com.mysql.jdbc.Driver.java

private final static CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList<>();

static {

try {

//并发安全的想一个copyOnWriteList中方

java.sql.DriverManager.registerDriver(new Driver());

} catch (SQLException E) {

throw new RuntimeException(“Can’t register driver!”);

}

}

4.最终Driver全部注册并初始化完毕,开始执行DriverManager.getConnection(url, “root”, “root”)方法并返回。

使用实例

四个项目:spiInterface、spiA、spiB、spiDemo

spiInterface中定义了一个com.zs.IOperation接口。

spiA、spiB均是这个接口的实现类,服务提供者。

spiDemo作为客户端,引入spiA或者spiB依赖,面向接口编程,通过spi的方式获取具体实现者并执行接口方法。

├─spiA

│ └─src

│ ├─main

│ │ ├─java

│ │ │ └─com

│ │ │ └─zs

│ │ ├─resources

│ │ │ └─META-INF

│ │ │ └─services

│ │ └─webapp

│ │ └─WEB-INF

│ └─test

│ └─java

├─spiB

│ └─src

│ ├─main

│ │ ├─java

│ │ │ └─com

│ │ │ └─zs

│ │ ├─resources

│ │ │ └─META-INF

│ │ │ └─services

最后,附一张自己面试前准备的脑图:

image

面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典

  • Java核心知识整理

image

  • Spring全家桶(实战系列)

image.png

Step3:刷题

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

以下是我私藏的面试题库:

image

很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。

最后祝愿各位身体健康,顺利拿到心仪的offer!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

Step3:刷题

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

以下是我私藏的面试题库:

[外链图片转存中…(img-6yckvjxM-1715254692392)]

很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。

最后祝愿各位身体健康,顺利拿到心仪的offer!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Cloud 微服务架构实战代码是一个基于 Spring Cloud 微服务解决方案的实践项目。它通过将常见的微服务技术组件和应用场景进行集成和示例演示,使读者能够深入了解和学习 Spring Cloud 微服务架构的实际应用。 该项目包含多个模块,其中包括注册中心(Eureka)、配置中心(Config)、网关(Zuul)、负载均衡(Ribbon)、链路跟踪(Sleuth)、熔断器(Hystrix)等,涵盖了微服务架构中的关键技术组件。在实现过程中,项目采用了 Spring Boot 来简微服务架构的搭建和开发,并以 Maven 进行依赖管理和构建。 通过该项目的学习,读者可以了解到微服务架构的基本概念、实际应用场景和解决方案,掌握 Spring Cloud 微服务架构的相关技术和工具的实际应用,了解微服务架构的开发和部署流程,掌握基于 Spring Boot 的微服务开发和集成方法,从而提高微服务架构设计实现和部署能力。 总之,Spring Cloud 微服务架构实战代码是一份完整的微服务架构实践项目,它可以帮助读者深入学习和了解微服务架构的实际应用,并具备较高的实际参考价值。 ### 回答2: Spring Cloud是一个开源的微服务架构实战代码,能够让开发人员在构建分布式系统时快速开发和部署微服务。它诞生于Spring项目之上,提供了基于Spring Boot的一套开发工具和服务,可以方便地管理和实现微服务架构的各项需求。 Spring Cloud包含了许多组件,如Eureka、Feign、Hystrix、Zuul等,这些组件都可以独立使用,也可以混合使用,相互之间的集成非常容易。例如,Eureka提供了服务注册与发现的能力,Feign支持微服务之间的远程调用,Hystrix可以提供服务的自我保护机制,Zuul可以提供API网关的功能,等等。 通过使用Spring Cloud,开发人员可以有效地解决微服务中需要处理的分布式问题,例如服务发现、服务注册、服务负载均衡、熔断、容错、路由、安全等等。此外,Spring Cloud还提供了一些常用的开发工具,如Spring Cloud Config,它可以帮助团队在开发和发布过程中有效地管理和配置系统的环境和配置文件。 总之,Spring Cloud是一套非常完善,且易于集成、扩展的微服务架构实战代码,尤其适用于企业级和大型系统的开发。它能够快速地实现微服务的各项技术需求,提高开发效率,使得开发人员更加专注于业务逻辑的开发,而不用再花费大量时间和精力处理微服务本身的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值