java运算符和表达式基础选择题,二(4)

String managementContextPath = env.getProperty(“management.server.servlet.context-path”);// nullable. should be wrapped into optional

Integer jmxPort = env.getProperty(“com.sun.management.jmxremote.port”, Integer.class);//nullable

EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);

instance.setNonSecurePort(serverPort);

instance.setInstanceId(getDefaultInstanceId(env));

instance.setPreferIpAddress(preferIpAddress);

instance.setSecurePortEnabled(isSecurePortEnabled);

if (StringUtils.hasText(ipAddress)) {

instance.setIpAddress(ipAddress);

}

if(isSecurePortEnabled) {

instance.setSecurePort(serverPort);

}

if (StringUtils.hasText(hostname)) {

instance.setHostname(hostname);

}

String statusPageUrlPath = getProperty(“eureka.instance.status-page-url-path”);

String healthCheckUrlPath = getProperty(“eureka.instance.health-check-url-path”);

if (StringUtils.hasText(statusPageUrlPath)) {

instance.setStatusPageUrlPath(statusPageUrlPath);

}

if (StringUtils.hasText(healthCheckUrlPath)) {

instance.setHealthCheckUrlPath(healthCheckUrlPath);

}

ManagementMetadata metadata = managementMetadataProvider.get(instance, serverPort,

serverContextPath, managementContextPath, managementPort);

if(metadata != null) {

instance.setStatusPageUrl(metadata.getStatusPageUrl());

instance.setHealthCheckUrl(metadata.getHealthCheckUrl());

if(instance.isSecurePortEnabled()) {

instance.setSecureHealthCheckUrl(metadata.getSecureHealthCheckUrl());

}

Map<String, String> metadataMap = instance.getMetadataMap();

if (metadataMap.get(“management.port”) == null) {

metadataMap.put(“management.port”, String.valueOf(metadata.getManagementPort()));

}

} else {

//without the metadata the status and health check URLs will not be set

//and the status page and health check url paths will not include the

//context path so set them here

if(StringUtils.hasText(managementContextPath)) {

instance.setHealthCheckUrlPath(managementContextPath + instance.getHealthCheckUrlPath());

instance.setStatusPageUrlPath(managementContextPath + instance.getStatusPageUrlPath());

}

}

setupJmxPort(instance, jmxPort);

return instance;

}

//注册DiscoveryClient服务发现客户端,它是spring-cloud-commons:2.0.1.RELEASE SpringCloud公共抽象包中的(org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient),

//是Spring Cloudd的服务发现抽象接口 EurekaDiscoveryClient是它的实现

@Bean

public DiscoveryClient discoveryClient(EurekaInstanceConfig config, EurekaClient client) {

return new EurekaDiscoveryClient(config, client);

}

//Eureak服务注册器,他是SpringCloud 在Netflix标准上拓展出来的,提供了服务注册,取消注册,设置服务状态,获取服务状态方法,ServiceRegistry负责服务注册,DiscoveryClient负责服务发现

@Bean

public EurekaServiceRegistry eurekaServiceRegistry() {

return new EurekaServiceRegistry();

}

//EurekaAutoServiceRegistration :eureka服务自动注册器

@Bean

@ConditionalOnBean(AutoServiceRegistrationProperties.class)

@ConditionalOnProperty(value = “spring.cloud.service-registry.auto-registration.enabled”, matchIfMissing = true)

public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry,

EurekaRegistration registration) {

return new EurekaAutoServiceRegistration(context, registry, registration);

}

//取消注册

@Override

public void stop() {

this.serviceRegistry.deregister(this.registration);

this.running.set(false);

}

//EureakClient配置,该配置没有刷新功能

@Configuration

@ConditionalOnMissingRefreshScope //不可刷新

protected static class EurekaClientConfiguration {

@Autowired

private ApplicationContext context;

@Autowired

private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;

//注册EurekaClient 客户端对象 , 它有一个实现 DiscoveryClient ,

//这个实现 DiscoveryClient 是eureka-client:1.9.3包里面的,是Euraek的服务发现的核心实现

@Bean(destroyMethod = “shutdown”)

@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)

public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config) {

return new CloudEurekaClient(manager, config, this.optionalArgs,

this.context);

}

//注册ApplicationInfoManager ,该对象用来管理 InstanceInfo

@Bean

@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)

public ApplicationInfoManager eurekaApplicationInfoManager(

EurekaInstanceConfig config) {

InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);

return new ApplicationInfoManager(config, instanceInfo);

}

//注册EurekaRegistration,它是Eureka实例的服务注册信息,开启自动注册时,该对象才会被注册

@Bean

@ConditionalOnBean(AutoServiceRegistrationProperties.class)

@ConditionalOnProperty(value = “spring.cloud.service-registry.auto-registration.enabled”, matchIfMissing = true)

public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,

CloudEurekaInstanceConfig instanceConfig,

ApplicationInfoManager applicationInfoManager,

@Autowired(required = false) ObjectProvider healthCheckHandler) {

return EurekaRegistration.builder(instanceConfig)

.with(applicationInfoManager)

.with(eurekaClient)

.with(healthCheckHandler)

.build();

}

}

//这里也是EurekaClient的配置,只是可刷新的

@Configuration

@ConditionalOnRefreshScope

protected static class RefreshableEurekaClientConfiguration {

@Autowired

private ApplicationContext context;

@Autowired

private AbstractDiscoveryClientOptionalArgs<?> optionalArgs;

//注册Eureak客户端EurekaClient, @Lazy 懒初始化,该bean被用到的时候会被创建

//EurekaClient有一个实现 DiscoveryClient这个实现 是eureka-client:1.9.3包里面的,是Euraek的服务发现的核心实现

@Bean(destroyMethod = “shutdown”)

@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)

@org.springframework.cloud.context.config.annotation.RefreshScope

@Lazy

public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance) {

manager.getInfo(); // force initialization

return new CloudEurekaClient(manager, config, this.optionalArgs,

this.context);

}

//注册ApplicationInfoManager,它是InstanceInfo的管理器

@Bean

@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)

@org.springframework.cloud.context.config.annotation.RefreshScope

@Lazy

public ApplicationInfoManager eurekaApplicationInfoManager(EurekaInstanceConfig config) {

//注意:这里的InstanceInfo被创建的状态是InstanceStatus.STARTING;后面在初始化的过程中会修改为 InstanceStatus.UP;

InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);

return new ApplicationInfoManager(config, instanceInfo);

}

@Bean

@org.springframework.cloud.context.config.annotation.RefreshScope

@ConditionalOnBean(AutoServiceRegistrationProperties.class)

@ConditionalOnProperty(value = “spring.cloud.service-registry.auto-registration.enabled”, matchIfMissing = true)

public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient,

CloudEurekaInstanceConfig instanceConfig,

ApplicationInfoManager applicationInfoManager,

@Autowired(required = false) ObjectProvider healthCheckHandler) {

return EurekaRegistration.builder(instanceConfig)

.with(applicationInfoManager)

.with(eurekaClient)

.with(healthCheckHandler)

.build();

}

}

…省略…

//健康指示器,用来管理服务的健康状况

@Configuration

@ConditionalOnClass(Health.class)

protected static class EurekaHealthIndicatorConfiguration {

@Bean

@ConditionalOnMissingBean

@ConditionalOnEnabledHealthIndicator(“eureka”)

public EurekaHealthIndicator eurekaHealthIndicator(EurekaClient eurekaClient,

EurekaInstanceConfig instanceConfig, EurekaClientConfig clientConfig) {

return new EurekaHealthIndicator(eurekaClient, instanceConfig, clientConfig);

}

}

总结一下:这里注册了很多对象比较重要的有:

1.EurekaClientConfigBean :这个类实现了netflix 的 EurekaClientConfig客户端配置接口,是对Eureka客户端的配置对象,即我们在配置文件中配置的 eureka.client 节点下的配置都会被封装到该对象中。

2.EurekaInstanceConfigBean: 该类实现了netflix的EurekaInstanceConfig接口,是的服务实例信息配置,ApplicationManager通过该接口用来构建InstanceConfig,比如我们在配置文件中配置的eureka.instance 开头的配置就会配置到该对象中。

3.DiscoveryClient:注册了DiscoveryClient服务发现客户端接口,默认实现是EurekaDiscoveryClient。这个类来源于spring-cloud-common.2.0.1.jar 这个包,这个包是springcloud的抽象包的公共包里面制定了一系列公共的API,而DiscoveryClient中包含了服务发现的基本公共方法

4.配置了一些客户端自动注册组件

  • EurekaServiceRegistry: Eureak服务注册器,他是SpringCloud 在Netflix标准上拓展出来的,提供了服务注册,取消注册, 关闭服务,设置服务状态,获取服务状态方法

  • EurekaRegistration: 它是Eureka实例的服务注册信息对象,开启自动注册时,该对象才会被注册,EurekaServiceRegistry负责服务注册,EurekaRegistration存放服务注册信息

  • EurekaAutoServiceRegistration: Eureka服务自动注册器,用来注册EurekaRegistration信息

5.EurekaClient:这里通过CloudEurekaClient来实例化,他是用来和EureakServer进行交互,是netflix提供的接口类,它还有个比较重要的实现 DiscoveryClient 主要负责服务发现,这个是与注册中心EureakServer交互的最核心的实现,包括服务注册,注册表拉取,服务续约等等功能都在里面提现。需要注意的是该Bean在注册的时候使用了@Lazy进行延迟创建

6.ApplicationInfoManager:这个类是用来管理实例注册信息InstanceInfo的,其中还包括了对实例状的态监听机制

7.EurekaHealthIndicator:这个是用作服务的健康检查的,以及提供了获取服务状态,以及获取Applications服务注册表等方法

2.EurekaAutoServiceRegistration:Eureaka自动注册

spring-cloud-commons-2.0.1.RELEASE.jar SpringCloud公共包中/META-INF/spring.factories配置文件中有AutoServiceRegistrationAutoConfiguration自动配置类,当应用启动SpringBoot会扫描到该自动配置类,然后注册到Spring容器

AutoConfiguration

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\

org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration

ServiceRegistryAutoConfiguration是配置注册的服务的端点信息,可通过端点 “/service-registry”查看到服务注册情况

@Configuration

public class ServiceRegistryAutoConfiguration {

@ConditionalOnBean(ServiceRegistry.class)

@ConditionalOnClass(Endpoint.class)

protected class ServiceRegistryEndpointConfiguration {

@Autowired(required = false)

private Registration registration;

@Bean

@ConditionalOnEnabledEndpoint

public ServiceRegistryEndpoint serviceRegistryEndpoint(ServiceRegistry serviceRegistry) {

ServiceRegistryEndpoint endpoint = new ServiceRegistryEndpoint(serviceRegistry);

endpoint.setRegistration(registration);

return endpoint;

}

}

}


//查看注册服务端点

@Endpoint(id = “service-registry”)

public class ServiceRegistryEndpoint {

private final ServiceRegistry serviceRegistry;

private Registration registration;

public ServiceRegistryEndpoint(ServiceRegistry<?> serviceRegistry) {

this.serviceRegistry = serviceRegistry;

}

public void setRegistration(Registration registration) {

this.registration = registration;

}

@WriteOperation

public ResponseEntity<?> setStatus(String status) {

Assert.notNull(status, “status may not by null”);

if (this.registration == null) {

return ResponseEntity.status(HttpStatus.NOT_FOUND).body(“no registration found”);

}

this.serviceRegistry.setStatus(this.registration, status);

return ResponseEntity.ok().build();

}

//获取服务状态

@ReadOperation

public ResponseEntity getStatus() {

if (this.registration == null) {

return ResponseEntity.status(HttpStatus.NOT_FOUND).body(“no registration found”);

}

return ResponseEntity.ok().body(this.serviceRegistry.getStatus(this.registration));

}

}

AutoServiceRegistrationAutoConfiguration是开启服务自动注册其中注入了AutoServiceRegistration确保该类会被注册,源码如下

@Configuration

@Import(AutoServiceRegistrationConfiguration.class)

@ConditionalOnProperty(value = “spring.cloud.service-registry.auto-registration.enabled”, matchIfMissing = true)

public class AutoServiceRegistrationAutoConfiguration {

@Autowired(required = false)

private AutoServiceRegistration autoServiceRegistration;

@Autowired

private AutoServiceRegistrationProperties properties;

@PostConstruct

protected void init() {

if (autoServiceRegistration == null && this.properties.isFailFast()) {

throw new IllegalStateException(“Auto Service Registration has been requested, but there is no AutoServiceRegistration bean”);

}

}

}

EurekaAutoServiceRegistration是Eureka的自动注册器,在EurekaClientAutoConfiguration中对EurekaAutoServiceRegistration做了Bean的定义,当开启spring.cloud.service-registry.auto-registration.enabled=true(默认)该Bean注册起效 , 它是 AutoServiceRegistration的实现

在这里插入图片描述

EurekaAutoServiceRegistration 源码如下:

//自动注册器

public class EurekaAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered {

private static final Log log = LogFactory.getLog(EurekaAutoServiceRegistration.class);

private AtomicBoolean running = new AtomicBoolean(false);

private int order = 0;

private AtomicInteger port = new AtomicInteger(0);

private ApplicationContext context;

//服务注册器

private EurekaServiceRegistry serviceRegistry;

//服务注册信息登记

private EurekaRegistration registration;

public EurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry serviceRegistry, EurekaRegistration registration) {

this.context = context;

this.serviceRegistry = serviceRegistry;

this.registration = registration;

}

//开启服务注册

@Override

public void start() {

// only set the port if the nonSecurePort or securePort is 0 and this.port != 0

if (this.port.get() != 0) {

if (this.registration.getNonSecurePort() == 0) {

this.registration.setNonSecurePort(this.port.get());

}

if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {

this.registration.setSecurePort(this.port.get());

}

}

// only initialize if nonSecurePort is greater than 0 and it isn’t already running

// because of containerPortInitializer below

if (!this.running.get() && this.registration.getNonSecurePort() > 0) {

//调用服务注册器进行服务注册

this.serviceRegistry.register(this.registration);

//发布一个服务注册事件

this.context.publishEvent(

new InstanceRegisteredEvent<>(this, this.registration.getInstanceConfig()));

this.running.set(true);

}

}

@Override

public void stop() {

//服务停止,取消服务注册

this.serviceRegistry.deregister(this.registration);

this.running.set(false);

}

@Override

public boolean isRunning() {

//获取服务状态是否运行

return this.running.get();

}

@Override

public int getPhase() {

return 0;

}

@Override

public boolean isAutoStartup() {

return true;

}

//停止服务

@Override

public void stop(Runnable callback) {

stop();

callback.run();

}

@Override

public int getOrder() {

return this.order;

}

//监听web启动完成事件,执行start()方法开启服务注册

@EventListener(WebServerInitializedEvent.class)

public void onApplicationEvent(WebServerInitializedEvent event) {

// TODO: take SSL into account

int localPort = event.getWebServer().getPort();

if (this.port.get() == 0) {

log.info("Updating port to " + localPort);

this.port.compareAndSet(0, localPort);

start();

}

}

//监听应用关闭事件,执行stop()方法

@EventListener(ContextClosedEvent.class)

public void onApplicationEvent(ContextClosedEvent event) {

if( event.getApplicationContext() == context ) {

stop();

}

}

}

EurekaAutoServiceRegistration监听了应用启动事件,调用EurekaServiceRegistry.register进行服务注册,同时监听应用关闭事件,调用EurekaServiceRegistry.deregister取消服务注册

3.EurekaServiceRegistry:服务注册器

EurekaServiceRegistry是Eureak服务注册器,他是SpringCloud 在Netflix标准ServiceRegistry上拓展出来的,提供了服务注册,取消注册, 关闭服务,设置服务状态,获取服务状态方法

在这里插入图片描述

ServiceRegistryEureakaServiceRegistry的接口,他是Netflix的服务发现抽象,ServiceRegistry需要依赖EurekaRegistration,EurekaRegistration是ServiceInstance的实现它约定了服务发现的实例应用的通用的信息

在这里插入图片描述

在应用启动时,EurekaAutoServiceRegistration会监听应用启动完成事件,在start()方法中调用,EureakaServiceRegistry.register方法开始服务注册,源码如下

//服务注册

public class EurekaServiceRegistry implements ServiceRegistry {

private static final Log log = LogFactory.getLog(EurekaServiceRegistry.class);

//注册方法,注册EurekaRegistration

@Override

public void register(EurekaRegistration reg) {

//初始化客户端,该方法会触发 EurekaClient 的创建

maybeInitializeClient(reg);

if (log.isInfoEnabled()) {

log.info("Registering application " + reg.getInstanceConfig().getAppname()

  • " with eureka with status "

  • reg.getInstanceConfig().getInitialStatus());

}

//初始化客户端状态,把InstanceStatus设置为 InstanceStatus.UP;

reg.getApplicationInfoManager()

.setInstanceStatus(reg.getInstanceConfig().getInitialStatus());

//注册健康检查处理器

reg.getHealthCheckHandler().ifAvailable(healthCheckHandler ->

reg.getEurekaClient().registerHealthCheck(healthCheckHandler));

}

//初始化客户端,reg.getEurekaClient()会触发EureakClient(DiscoveryClient)的初始化

private void maybeInitializeClient(EurekaRegistration reg) {

// force initialization of possibly scoped proxies

reg.getApplicationInfoManager().getInfo();

//初始化Eurak客户端

reg.getEurekaClient().getApplications();

}

//取消注册,设置服务状态为down

@Override

public void deregister(EurekaRegistration reg) {

if (reg.getApplicationInfoManager().getInfo() != null) {

if (log.isInfoEnabled()) {

log.info("Unregistering application " + reg.getInstanceConfig().getAppname()

  • " with eureka with status DOWN");

}

reg.getApplicationInfoManager().setInstanceStatus(InstanceInfo.InstanceStatus.DOWN);

//shutdown of eureka client should happen with EurekaRegistration.close()

//auto registration will create a bean which will be properly disposed

//manual registrations will need to call close()

}

}

//设置服务注册状态

@Override

public void setStatus(EurekaRegistration registration, String status) {

InstanceInfo info = registration.getApplicationInfoManager().getInfo();

//TODO: howto deal with delete properly?

if (“CANCEL_OVERRIDE”.equalsIgnoreCase(status)) {

registration.getEurekaClient().cancelOverrideStatus(info);

return;

}

//TODO: howto deal with status types across discovery systems?

InstanceInfo.InstanceStatus newStatus = InstanceInfo.InstanceStatus.toEnum(status);

registration.getEurekaClient().setStatus(newStatus, info);

}

//获取服务注册状态

@Override

public Object getStatus(EurekaRegistration registration) {

String appname = registration.getInstanceConfig().getAppname();

String instanceId = registration.getInstanceConfig().getInstanceId();

InstanceInfo info = registration.getEurekaClient().getInstanceInfo(appname, instanceId);

HashMap<String, Object> status = new HashMap<>();

if (info != null) {

status.put(“status”, info.getStatus().toString());

status.put(“overriddenStatus”, info.getOverriddenStatus().toString());

} else {

status.put(“status”, UNKNOWN.toString());

}

return status;

}

public void close() {

}

}

EurekaServiceRegistry中register方法初始化了Eureka客户端,以及注册了健康检查处理器,在private void maybeInitializeClient(EurekaRegistration reg)方法中reg.getEurekaClient().getApplications();会触发在EurekaClientAutoConfiguration自动配置中对EureakClient的延迟创建,使用的EurekaClient的实现com.netflix.discovery.DiscoveryClient

4.DiscoveryClient:服务发现

这个类来源于 eureka-client-19.3.jar这个包 ,DiscoveryClient这个类是用来和Eureak Server服务端做交互,通过程序的主入口类上的@EnableDiscoveryClient标签开启,该类在EurekaClientAutoConfiguration中被注册,该类的继承关系如下:

在这里插入图片描述

CloudEurekaClient实现了 com.netflix.discovery.DiscoveryClient接口,DiscoveryClient实现了com.netflix.discovery.EurekaClient接口,

EurekaClient是Netflix提供的服务发现抽象的接口,DiscoveryClient是其默认实现,CloudEurekaClient是spring cloud的提供的,其中重写了onCacheRefreshed()方法,目的是在刷新本地注册表缓存之后用于使用ApplicationEventPublisher发布HeartbeatEvent事件。

com.netflix.discovery.shared.LookupService

服务发现顶级接口,里面包含了服务查找方法

/**

  • Lookup service for finding active instances.

  • 用来查找活动的服务实例

*/

public interface LookupService {

/**

根据应用名获取该名字对应的应用,Application中描述了该appName对应的多个应用实例

*/

Application getApplication(String appName);

/**

获取所有的应用注册列表,Applications是eureka server返回的所有注册信息

*/

Applications getApplications();

/**

根据ID获取服务实例信息信息对象列表

*/

List getInstancesById(String id);

InstanceInfo getNextServerFromEureka(String virtualHostname, boolean secure);

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

学习视频:

大厂面试真题:

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
*/

Applications getApplications();

/**

根据ID获取服务实例信息信息对象列表

*/

List getInstancesById(String id);

InstanceInfo getNextServerFromEureka(String virtualHostname, boolean secure);

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-QppBruQX-1713310183708)]

[外链图片转存中…(img-lXgH3mEr-1713310183708)]

[外链图片转存中…(img-QleRcvXq-1713310183709)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

学习视频:

[外链图片转存中…(img-TveKHAaN-1713310183709)]

大厂面试真题:

[外链图片转存中…(img-VPgZzAHm-1713310183709)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值