当前位置: 首页 > news >正文

Spring 原理(很多面试题)

本节目标

1. 掌握Bean的作⽤域和⽣命周期

2. 了解SpringBoot ⾃动配置流程

1. Bean的作用域

        1.1 概念

        在Spring IoC&DI阶段, 我们学习了Spring是如何帮助我们管理对象的.

        1. 通过 @Controller , @Service , @Repository , @Component , @Configuration , @Bean 来声明Bean对象.(告诉spring 帮我管理对象) 

        2. 通过 ApplicationContext 或者 BeanFactory 来获取对象

        3. 通过 @Autowired , Setter ⽅法或者构造⽅法等来为应⽤程序注⼊所依赖的Bean对象

我们来简单回顾⼀下

        1. 通过 @Bean 声明bean , 把bean存在Spring容器中

        2. 从Spring容器中获取Bean

        也可以通过在代码中直接注⼊ApplicationContext的⽅式来获取Spring容器

结果:获取成功

修改代码, 从Spring容器中多次获取Bean: 发现重新获取之后,打印的是修改后的,因此我们推测是同一个对象

我们通过打印地址来进行比对: 发现一样,说明是一个对象

        发现输出的bean对象地址值是⼀样的, 说明每次从Spring容器中取出来的对象都是同⼀个.

        这也是"单例模式"

        单例模式: 确保⼀个类只有⼀个实例,多次创建也不会创建出多个实例

        默认情况下, Spring容器中的bean都是单例的, 这种⾏为模式, 我们就称之为Bean的作⽤域.

        Bean 的作⽤域是指 Bean 在 Spring 框架中的某种⾏为模式.

        ⽐如单例作⽤域: 表⽰ Bean 在整个 Spring 中只有⼀份, 它是全局共享的. 那么当其他⼈修改了这个值之后, 那么另⼀个⼈读取到的就是被修改的值.

        1.2 Bean的作用域

        在Spring中⽀持6种作⽤域,后4种在Spring MVC环境才⽣效

        1. singleton:单例作⽤域

        2. prototype:原型作⽤域(多例作⽤域)

        3. request:请求作⽤域

        4. session:会话作⽤域

        5. Application: 全局作⽤域

        6. websocket:HTTP WebSocket 作⽤域

作⽤域说明
singleton每个Spring IoC容器内同名称的bean只有⼀个实例(单例)(默认)
prototype每次使⽤该bean时会创建新的实例(⾮单例)(只要我使用这个bean,就会创建新的bean,获取的对象不是一个对象)
request每个HTTP 请求⽣命周期内, 创建新的实例(web环境中, 了解)(一个请求里面,得到的是一个对象)
session每个HTTP Session⽣命周期内, 创建新的实例(web环境中, 了解)(在一个会话,得到的是一个对象,来来回回的称之为一个会话)
application每个ServletContext⽣命周期内, 创建新的实例(web环境中, 了解)
websocket每个WebSocket⽣命周期内, 创建新的实例(web环境中, 了解)

范围从小到大.

        我们进行演示

        单例的作用域

        原型模型的作用域

对象产生的时机

request请求: 同一个请求对象一样,反之不一样

session: 同一个对话,(同一个浏览器,就说明是同一个用户)对象一样

application: 在⼀个应⽤中, 多次访问都是同⼀个对象(和单例很像)

singleton和application的区别

        Application scope就是对于整个web容器来说, bean的作⽤域是ServletContext级别的. 这个和singleton有点类似,区别在于: Application scope是ServletContext的单例, singleton是⼀个ApplicationContext的单例. 在⼀个web容器中ApplicationContext可以有多个. (web容器可以放多个web服务)

        关于@AppliactionScop和其他的

2. Bean的生命周期

        2.1 Bean的生命周期的概念(要毁结合源码来讲一下它的过程)

        ⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程, 我们把这个过程就叫做⼀个对象的⽣命周期. Bean 的⽣命周期分为以下5个部分:(一般在Spring里面的对象才称之为Bean)

        1. 实例化(为Bean分配内存空间)

        2. 属性赋值(Bean注⼊和装配, ⽐如 @AutoWired )

        3. 初始化(初始化里面的通知,好好理解一下)

                a. 执⾏各种通知, 如 BeanNameAware , BeanFactoryAware ,ApplicationContextAware 的接⼝⽅法.

                b. 执⾏初始化⽅法

        ▪ xml定义 init-method

        ▪ 使⽤注解的⽅式 @PostConstruct

        ▪ 执⾏初始化后置⽅法( BeanPostProcessor )

        4. 使⽤Bean

        5. 销毁Bean

        a. 销毁容器的各种⽅法, 如 @PreDestroy , DisposableBean 接⼝⽅法, destroymethod.

        实例化和属性赋值对应构造⽅法和setter⽅法的注⼊. 初始化和销毁是⽤⼾能⾃定义扩展的两个阶段, 可以在实例化之后, 类加载完成之前进⾏⾃定义"事件"处理.

        ⽐如我们现在需要买⼀栋房⼦, 那么我们的流程是这样的:

        1. 先买房(实例化, 从⽆到有)

        2. 装修(设置属性)

        3. 买家电, 如洗⾐机, 冰箱, 电视, 空调等([各种]初始化,可以⼊住);

        4. ⼊住(使⽤ Bean)

        5. 卖房(Bean 销毁)

         2.2 代码演示

package org.xiaobai.spring_principle.component;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xiaobai.spring_principle.model.Dog;

@Component
public class BeanLifeComponent implements BeanNameAware {
    private Dog singletonDog;
    //1.实例化
    public BeanLifeComponent(){
        System.out.println("执行构造函数,实例化.....");
    }
    //2.属性赋值
    @Autowired
    public void setSingletonDog(Dog singletonDog){
    this.singletonDog = singletonDog;
        System.out.println("执行setSingletonDog,属性赋值....");
    }
    //3. 初始化
    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName: "+name);
    }
    @PostConstruct
    public void init(){
        System.out.println("执行postConstruct, 初始化....");
    }
    //4. bean使用
    public void use(){
        System.out.println("使用use方法,bean的使用....");
    }
    //5. bean销毁(销毁前做的处理)
    @PreDestroy
    public void destroy(){
        System.out.println("使用destroy方法,bean的销毁...");
    }
}

        我们执行方法

        对应关系

        关于初始化的理解

        (不加@autowired的对象)运行时生成的对象(动态生成)也可以放在init里面

        

        2.3 源码阅读

        1. createBeanInstance() -> 实例化

        2. populateBean() -> 属性赋值

        3. initializeBean() -> 初始化

3. Spring Boot自动配置(最复杂的面试题)

        SpringBoot的⾃动配置就是当Spring容器启动后, ⼀些配置类, bean对象等就⾃动存⼊到了IoC容器中, 不需要我们⼿动去声明, 从⽽简化了开发, 省去了繁琐的配置操作.

        1> 自己声明的对象

        2> 像事务那一块,spring里面内置的对象(比如这个)

        我们关心他们是怎么被spring加载进来的

        SpringBoot⾃动配置, 就是指SpringBoot是如何将依赖jar包中的配置类以及Bean加载到Spring IoC容器中的.

        我们学习主要分以下两个⽅⾯:

        1. Spring 是如何把对象加载到SpringIoC容器中的

        2. SpringBoot 是如何实现的

        3.1 Spring 加载Bean

        3.1.1 问题描述

        需求: 使⽤Spring管理第三⽅的jar包的配置

        引⼊第三⽅的包, 其实就是在该项⽬下,引⼊第三⽅的代码, 我们采⽤在该项⽬下创建不同的⽬录来模拟第三⽅的代码引⼊

        没有 rg.test.XiaoConfig 这个类型的Bean(下面图显示)

      

      3.1.2 原因分析

        Spring通过五⼤注解和 @Bean 注解可以帮助我们把Bean加载到SpringIoC容器中, 以上有个前提就是这些注解类需要和SpringBoot启动类在同⼀个⽬录下 ( @SpringBootApplication 标注的类 就是SpringBoot项⽬的启动类).

        启动类所在⽬录为: com.example.demo , ⽽ XiaoConfig 这个类在rg.test.XiaoConfig 下, 所以SpringBoot并没有扫描到.

        3.1.3 解决⽅案

        我们需要指定路径或者引⼊的⽂件, 告诉Spring, 让Spring进⾏扫描到.

         常⻅的解决⽅案有两种:

        1. @ComponentScan 组件扫描

        2. @Import 导⼊(使⽤@Import导⼊的类会被Spring加载到IoC容器中)

        我们通过代码来看如何解决        

             3.1.3.1 加扫描组建

         我们发现刚刚报错的代码执行成功了

        但是我们的spring引入了很多的包,我们的spring难道都要通过组件一个一个加进来吗?

        ⾮常明显, 没有.(因为我们引⼊第三⽅框架时, 没有加扫描路径. ⽐如mybatis)

        如果Spring Boot采⽤这种⽅式, 当我们引⼊⼤量的第三⽅依赖, ⽐如Mybatis, jackson等时, 就需要在启动类上配置不同

        依赖需要扫描的包, 这种⽅式会⾮常繁琐.

        3.1.3.2 @Import

        @Import 导⼊主要有以下⼏种形式:

        1. 导⼊类

        2. 导⼊ ImportSelector 接⼝实现类

        我们在启动类里面使用@Import注解把类到进去

        然后观察结果,是可以的

        

        如果有多个类,我们也可以采用多类导入

        运行结果

        很明显, 这种⽅式也很繁琐.

        所以, SpringBoot依然没有采⽤.

        2. 导⼊ImportSelector接⼝实现类
        ImportSelector 接⼝实现类

        问题:

        但是他们都有⼀个明显的问题, 就是使⽤者需要知道第三⽅依赖中有哪些Bean对象或配置类. 如果漏掉其中⼀些Bean, 很可能导致我们的项⽬出现⼤的事故.

        这对程序员来说⾮常不友好.

        依赖中有哪些Bean, 使⽤时需要配置哪些bean, 第三⽅依赖最清楚, 那能否由第三⽅依赖来做这件事呢?

        • ⽐较常⻅的⽅案就是第三⽅依赖给我们提供⼀个注解, 这个注解⼀般都以@EnableXxxx开头的注解,

        注解中封装的就是 @Import 注解

        1. 第三⽅依赖提供注解

        我们自己写一个注解

        2. 在启动类上使⽤第三⽅提供的注解

        

        3. 运⾏程序

可以看到, 这种⽅式也可以导⼊第三⽅依赖提供的Bean. 并且这种⽅式更优雅⼀点. SpringBoot采⽤的也是这种⽅式

        但是有时候我记不住注解,这该怎么解决?我们约定好放在一个地方,然后我要用就直接拿即可

这也就是为什么我们的启动类只用了一个@SpringBootApplication注解的就能够扫描到所有的类的原因.

        我们来看看启动类注解里面的组成

具体的解释: @SpringConfiguration @ComponentScan(这个是用力来扫描我们这个项目下面的包)

第三方包是: @SpringConfiguration和@EnableAutoConfiguration这俩个注解

        @EnableAutoConfiguration

@AutoConfiguration( @EnableAutoConfiguration里面的嵌套注解)

        我们来看一些更加具体的解释

        @SpringBootApplication

        @SpringBootApplication 是⼀个组合注解, 注解中包含了:

        1. 元注解

        JDK中提供了4个标准的⽤来对注解类型进⾏注解的注解类, 我们称之为 meta-annotation(元注解), 他们分别是:

        • @Target 描述注解的使⽤范围(即被修饰的注解可以⽤在什么地⽅)

        • @Retention 描述注解保留的时间范围

        • @Documented 描述在使⽤ javadoc ⼯具为类⽣成帮助⽂档时是否要保留其注解信息

        • @Inherited 使被它修饰的注解具有继承性(如果某个类使⽤了被@Inherited修饰的注解,则

其⼦类将⾃动具有该注解)

        2. @SpringBootConfiguration

        ⾥⾯就是@Configuration, 标注当前类为配置类, 其实只是做了⼀层封装改了个名字⽽已. (@Indexed注解,是⽤来加速应⽤启动的, 不⽤关⼼)

        3. @EnableAutoConfiguration (开启⾃动配置)

        Spring⾃动配置的核⼼注解, 下⾯详细讲解

        4. @ComponentScan (包扫描)

        可以通过 basePackageClasses 或 basePackages 来定义要扫描的特定包, 如果没有定义特定的包, 将从声明该注解的类的包开始扫描, 这也是为什么SpringBoot项⽬声明的注解类必须要在启动类的⽬录下.

        excludeFilters ⾃定义过滤器, 通常⽤于排除⼀些类, 注解等.

        3.2.2 @EnableAutoConfiguration 详解

        看下 @EnableAutoConfiguration 注解的实现:

        这个注解包含两部分:

        1. @Import({AutoConfigurationImportSelector.class})

        使⽤@Import注解,导⼊了实现ImportSelector接⼝的实现类.

        selectImports() ⽅法底层调⽤ getAutoConfigurationEntry() ⽅法, 获取可⾃动配置的配置类信息集合.

        

        getAutoConfigurationEntry() ⽅法通过调⽤getCandidateConfigurations(annotationMetadata, attributes) ⽅法获取在配置⽂件中配置的所有⾃动配置类的集合

        getCandidateConfigurations ⽅法的功能

        这⾥⾯包含了很多第三⽅依赖的配置⽂件(连续按两下shift可以查看对应的源码)

        1. 在加载⾃动配置类的时候, 并不是将所有的配置全部加载进来, ⽽是通过@Conditional等注解的判断进⾏动态加载.

        @Conditional是spring底层注解, 意思就是根据不同的条件, 来进⾏⾃⼰不同的条件判断,如果满⾜指定的条件,那么配置类⾥边的配置才会⽣效.

        2. META-INF/spring.factories⽂件是Spring内部提供的⼀个约定俗成的加载⽅式, 只需要在模块的

        META-INF/spring.factories⽂件中配置即可, Spring就会把相应的实现类注⼊到Spring容器中. 注: 会加载所有jar包下的classpath路径下的META-INF/spring.factories⽂件, 这样⽂件不⽌⼀个.

        可以看到, 配置⽂件中使⽤ @Bean 声明了⼀些对象, spring就会⾃动调⽤配置类中使⽤ @Bean 标识的⽅法, 并把对象注册到Spring IoC容器中.

        在加载⾃动配置类的时候, 并不是将所有的配置全部加载进来, ⽽是通过@Conditional等注解的判断进⾏动态加载

        @Conditional是spring底层注解, 意思就是根据不同的条件, 来进⾏⾃⼰不同的条件判断,如果满⾜指定的条件,那么配置类⾥边的配置才会⽣效。

        2. @AutoConfigurationPackage

        这个注解主要是导⼊⼀个配置⽂件 AutoConfigurationPackages.Registrar.class

        Registrar实现了 ImportBeanDefinitionRegistrar 类, 就可以被注解@Import导⼊到spring容器⾥.

        3.2.3 总结

        SpringBoot ⾃动配置原理的⼤概流程如下:

        当SpringBoot程序启动时, 会加载配置⽂件当中所定义的配置类, 通过 @Import 注解将这些配置类全部加载到Spring的IOC容器中, 交给IOC容器管理.

4. 总结

        1. Bean的作⽤域共分为6种: singleton, prototype, request, session, application和websocket.

        2. Bean的⽣命周期共分为5⼤部分: 实例化, 属性复制, 初始化, 使⽤和销毁

        3. SpringBoot的⾃动配置原理源码⼝是 @SpringBootApplication 注解, 这个注解封装了3个注

        ◦ @SpringBootConfiguration 标志当前类为配置类

        ◦ @ComponentScan 进⾏包扫描(默认扫描的是启动类所在的当前包及其⼦包)

        ◦ @EnableAutoConfiguration

        ▪ @Import 注解 : 读取当前项⽬下所有依赖jar包中 META-INF/spring.factories ,

        METAINF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports俩个文件里面定义的配置类(配置类中定义了@Bean注解标识的方法)

        ▪ @AutoConfigurationPackage : 把启动类所在的包下⾯所有的组件都注⼊到 Spring容器中

5. 补充面试题

        Spring中的事务什么时候失效?

        1> 非public  

        2> 异常类型(非runtime)

        3> 对象没有交给spring管理

        4> 事务传播机制的设置

        5> 数据库不支持事务

        三级缓存

        Spring是如何解决循环依赖的?答案即是Spring的三级缓存

这个问题或者换个问法:Spring是如何解决循环依赖的?答案即是Spring的三级缓存

        什么是循环依赖

        简单说,就是A对象依赖B对象,B对象⼜依赖A对象,类似的代码如下:

@Component
public class A{
@Autowired
private B b;
}
@Component
public class B{
@Autowired
private A a;

        其他还有很多种⽅式,如A依赖B,B依赖C,C依赖A,或是A依赖A⾃⼰,只要产⽣了依赖关系的闭环,即造成了循环依赖。

        那么,循环依赖会引发什么问题呢?理解这个问题先得理解Bean的⽣命周期,以下先回顾下


        Bean的生命周期回顾

        1. 启动容器:加载Bean

        2. 实例化Bean对象

        3. 依赖注⼊:装配Bean的属性

        4. 初始化Bean:执⾏aware接⼝⽅法、预初始化⽅法、初始化⽅法、后初始化⽅法

        5. 关闭容器:销毁Bean

        在以上第四个步骤执⾏完毕,才算⼀个初始化完成的Bean,也即Spring容器中完整的Bean对象。


 

        循环依赖的问题

        Spring容器保存Bean的⽅式,是采取缓存的⽅式:使⽤ Map<String, Object> 的结构,key为Bean的名称,value为Bean对象。需要使⽤时直接从缓存获取。

        如A、B互相依赖(循环依赖):

        1. 容器中没有A对象,实例化A对象

        2. 装配A中的B对象,发现B在容器中没有,需要先实例化B

        3. 实例化B对象

        4. 装配B中的A对象,发现A在容器中没有,需要先实例化A

        5. 重复第⼀个步骤

        这就套娃了, 你猜是先 StackOverflow 还是 OutOfMemory ?

        [PS]

        • Bean会依赖某些注⼊的Bean来完成初始化⼯作

        • 由于Spring⽀持构造⽅法注⼊,属性/Setter注⼊的⽅式,所以不能简单的先把所有对象全部实例化,放到缓存中,再全部执⾏初始化。原因很简单,此时所有对象的引⽤都可以获取到,但属性都是null,执⾏初始化甚⾄构造⽅法都可能出现空指针异常。

        那么我们说Spring能解决循环依赖,也不是所有的情况都可以解决,只有以下情况才⽀持。

        Spring不支持的循环依赖

        Spring框架在处理循环依赖时存在⼀些限制, 它不能解决所有类型的循环依赖问题 ⽐如以下循环依赖的场景, Spring并不⽀持(包含但不限于)

        1. 构造器循环依赖:当两个Bean在它们的构造器中相互依赖时,Spring⽆法解决这种循环依赖。

        Spring在创建Bean时会检查构造器中的循环依赖,并在发现时抛出BeanCurrentlyInCreationException 异常。 

        2. 原型Bean循环依赖:对于原型作⽤域(Prototype)的Bean,Spring不⽀持循环依赖。原型Bean的⽣命周期是短暂的,每次请求都会创建新实例,Spring容器不缓存原型Bean,因此⽆法提前暴露⼀个创建中的Bean来解决循环。

        3. 复杂的AOP场景下的循环依赖:在⼀些复杂的AOP(⾯向切⾯编程)场景中,如果Bean之间存在循环依赖,并且这些Bean被⽤于AOP代理,Spring可能⽆法解决这种循环依赖。

        Spring解决循环依赖

Spring是使⽤三级缓存的机制来解决循环依赖问题,以下为三级缓存的定义:

         三级缓存就是三个map

以下是部分说明:

        • 三级缓存singletonFactories中保存的是ObjectFactory对象(Bean⼯⼚),其中包含了

        BeanName,Bean对象,RootBeanDefinition,该⼯⼚可以⽣成Bean对象。

        • 由于Bean可能被代理,此时注⼊到其他Bean属性中的也应该是代理Bean。

        单例模式的A、B循环依赖执⾏流程如下:

        为什么要使用三级缓存

        依照以上三级缓存的流程,其实使⽤⼆级缓存也能满⾜循环依赖的注⼊:

        • 普通的IoC容器使⽤⼀级缓存即可,但⽆法解决循环依赖问题。

        • 解决循环依赖问题:使⽤⼆级缓存即可。⼀级缓存保存完整Bean,⼆级缓存保存提前曝光的不完整的Bean。

        • 需要AOP代理Bean时,有两种实现思路:

        (1)再加⼀级缓存

        (2)只使⽤⼆级缓存,其中⼆级缓存保存Bean的代理对象,代理对象中引⽤不完整的原始对象即可

        • Spring使⽤三级缓存保存ObjectFactory即Bean⼯⼚,在代码的层次设计及扩展性上都会更好。三级缓存的引⼊主要是为了解决代理相关的循环依赖问题,尤其是涉及到AOP时,代理对象的创建可能需要提前于Bean的完全初始化.

         在Spring 3.6之前,Spring通过使⽤⼀级和⼆级缓存来解决单例Bean的循环依赖问题,⽽从3.6版本开始,通过引⼊三级缓存,Spring能够更全⾯地处理包括AOP在内的更复杂的循环依赖情况。

        SpringMVC的流程(简要分析,有机会去翻翻源码)

        

        1> 发送request请求,然后通过dispathcherServlet去查找handle

        2> 根据handle找适配器

        3> 执行handle 

        4> 返回model and view

        5> 解析视图,填充视图,然后再进行返回response

        SpringMVC的请求响应步骤如下: 具体步骤:

        • 第⼀步:(发起)发起请求到前端控制器(DispatcherServlet)

        • 第⼆步:(查找)前端控制器请求HandlerMapping查找 Handler(可以根据xml配置、注解进⾏查找)

        • 第三步:(返回)处理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping会把请求映射为HandlerExecutionChain对象(包含⼀个Handler处理器(⻚⾯控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略

        • 第四步:(调⽤)前端控制器调⽤处理器适配器去执⾏Handler

        • 第五步:(执⾏)处理器适配器HandlerAdapter将会根据适配的结果去执⾏Handler

        • 第六步:(返回)Handler执⾏完成给适配器返回ModelAndView

        • 第七步:(接收)处理器适配器向前端控制器返回ModelAndView (ModelAndView是SpringMVC框架的⼀个底层对象,包括 Model和view)

        • 第⼋步:(解析)前端控制器请求视图解析器去进⾏视图解析 (根据逻辑视图名解析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可

        • 第九步:(返回)视图解析器向前端控制器返回View

        • 第⼗步:(渲染)前端控制器进⾏视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域)

        • 第⼗⼀步:(响应)前端控制器向⽤⼾响应结果

        以下是对出现的⼀些组件的介绍:

        (1) DispatcherServlet

        作⽤:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。

        (2) 处理器映射器HandlerMapping

        作⽤:根据请求的url查找Handler

        (3) 处理器适配器HandlerAdapter

        作⽤:按照特定规则(HandlerAdapter要求的规则)去执⾏Handler。 (4) 处理器Handler(程序员开发)

        注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执⾏Handler (5) 视图解析器ViewResolver

        作⽤:进⾏视图解析,根据逻辑视图名解析成真正的视图(6) 视图View(程序员开发)

        注意:View是⼀个接⼝,实现类⽀持不同的View类型(jsp、freemarker、pdfR) ps:不需要程序员开发的,需要程序员⾃⼰做⼀下配置即可

 

相关文章:

  • (下:补充——五个模型的理论基础)深度学习——图像分类篇章
  • 【星云 Orbit • STM32F4】03g. 按键玩法七:矩阵键盘单个触发
  • 迷你世界脚本方块接口:Block
  • 力扣hot 100之矩阵四题解法总结
  • 博客系统--测试报告
  • 基于SpringBoot和PostGIS的各省与地级市空间距离分析
  • 17、什么是智能指针,C++有哪几种智能指针【高频】
  • C#使用技巧
  • Deepseek+RAGFLOW部署教程
  • 计算机毕业设计SpringBoot+Vue.js在线课程管理系统(源码+文档+PPT+讲解)
  • JVM常用概念之垃圾回收设计与停顿
  • 学习C++常用词汇词组及缩写汇总
  • Node.js二:第一个Node.js应用
  • 蓝桥备赛(六)- C/C++输入输出
  • 在Spring Boot项目中将中文转换为拼音:从入门到实践
  • Hive之正则表达式
  • flink web ui未授权漏洞处理
  • 【行政区划获取】
  • 专业工具,杜绝一切垃圾残留!
  • surfaceflinger对INVALIDATE和REFRESH消息的处理
  • 最高人民法院、中国证监会联合发布《关于严格公正执法司法 服务保障资本市场高质量发展的指导意见》
  • 消息人士称泽连斯基已启程前往土耳其
  • 第十二届警博会在京开幕:12个国家和地区835家企业参展
  • 媒体:“西北大学副校长范代娣成陕西首富”系乌龙,但她的人生如同开挂
  • 李强会见巴西总统卢拉
  • 西北大学副校长成陕西首富?旗下巨子生物去年净利超20亿,到底持股多少