Spring核心知识全解析:从入门实战到进阶

Spring框架作为Java EE开发领域的标杆性框架,凭借其轻量级、分层架构设计,彻底解决了传统Java开发中代码耦合度高、配置繁琐等痛点。本文将从Spring框架基础认知出发,通过Hello World实战案例切入,逐步深入IOC容器、Bean管理、Bean作用域与生命周期等核心知识点,最后扩展Lombok与Spring的整合技巧,帮助开发者快速掌握Spring核心用法并提升开发效率。

一、Spring框架的核心认知

1.1 Spring框架概述

Spring是一款开源的设计层面框架,核心目标是解决业务逻辑层与其他各层的紧耦合问题,将面向接口的编程思想贯穿整个应用开发。它诞生于2003年,由Rod Johnson在其著作《Expert One-On-One J2EE Development and Design》中阐述的理念与原型衍生而来,专为简化企业级应用开发的复杂性而创建。

Spring最显著的优势在于其分层架构,开发者可按需选择使用框架中的特定组件,同时它为Java EE应用开发提供了一站式的集成解决方案。从本质上讲,Spring是一个分层的Java SE/EE full-stack(一站式)轻量级开源框架,其核心功能围绕两大核心机制展开:

  • IOC(控制反转) :将对象的创建权力从开发者手中反转给Spring框架管理,无需手动通过new关键字创建对象,极大降低了代码耦合度。

  • AOP(面向切面):在不修改原有源代码的前提下,对代码功能进行增强(如权限拦截、运行监控、事务管理等),实现代码的解耦与复用。

1.2 Spring框架的核心优势

Spring之所以能成为Java开发的主流框架,源于其强大的功能特性与易用性,具体优势如下:

  1. 解耦简化开发:Spring充当"对象工厂"的角色,统一管理所有对象的创建与依赖关系维护,通过IOC机制彻底解决代码紧耦合问题。

  2. 原生支持AOP编程:提供完善的AOP解决方案,可轻松实现日志记录、性能监控、权限校验等横切逻辑,无需侵入业务代码。

  3. 声明式事务管理:通过简单的配置即可完成事务管理,无需手动编写事务控制代码,降低了事务管理的复杂度与出错率。

  4. 便捷的测试支持:无缝集成Junit4等测试框架,通过注解即可快速实现Spring程序的单元测试与集成测试。

  5. 兼容主流开源框架:不排斥其他优秀开源框架,内部提供了对Struts2、Hibernate、MyBatis等框架的直接集成支持,降低技术选型成本。

  6. 简化Java EE API使用:对JDBC、JavaMail、JMS等难用的Java EE API进行封装,提供简洁的API调用方式,降低开发难度。

二、Spring入门实战:Hello World案例

本节通过经典的Hello World案例,演示Spring框架的基础使用流程,包括Maven工程创建、依赖导入、配置文件编写、代码实现与测试。

2.1 环境准备:创建Maven工程并导入依赖

首先创建Maven工程,在pom.xml文件中导入Spring核心依赖及相关辅助依赖:

XML 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.12</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

核心依赖说明:spring-context是Spring核心上下文依赖,包含IOC容器的核心实现;其他依赖用于日志输出与单元测试。

2.2 编写业务逻辑类

创建com.qcby.service.Demo类,实现简单的Hello World输出方法:

java 复制代码
package com.xxx.service;

public class Demo {
    public void hello() {
        System.out.println("hello world");
    }
}

2.3 编写Spring核心配置文件

resources目录下创建Spring核心配置文件applicationContext.xml(文件名可自定义,推荐使用默认名称),通过配置将Demo类交由Spring IOC容器管理:

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
           <!--IOC管理bean-->
    <!--id:类的唯一标识:类的全路径名-->
    <bean id="demo" class="com.xxx.service.Demo" />
</beans>

配置说明:<bean>标签用于定义Spring管理的对象,id属性是对象的唯一标识,class属性指定类的全路径名。

2.4 编写测试类

创建测试类com.qcby.servic.UserServiceTest,分别通过传统方式与Spring方式调用hello()方法,对比两种方式的差异:

java 复制代码
package com.xxx.servic;

import com.xxx.service.Demo;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserServiceTest {
    //spring写法:从IOC容器获取对象
    @Test
    public void run1(){
            //创建spring工厂
            ApplicationContext ac = new ClassPathXmlApplicationCoApplicationContext.xml");
            //获取bean对象
            Demo us = (Demo) ac.getBean("us");
            //调用方法
            us.hello();
    }

三、Spring核心:IOC容器深度解析

IOC(控制反转)是Spring框架的核心,而IOC容器则是IOC思想的具体落地实现。本节将深入讲解IOC思想的本质、IOC容器的底层原理及两种核心实现方式。

3.1 什么是IOC思想?

IOC(Inverse of Control,控制反转)是一种面向对象编程的设计原则,核心是"反转对象创建的控制权"。在传统Java开发中,若A类需要使用B类的方法,必须在A类内部通过new B()手动创建B对象,这种方式会导致代码紧耦合------若B类的构造方法发生变化,A类也需要同步修改。

更严重的是,若出现"循环依赖"(如A类依赖B类、B类依赖C类、C类依赖A类),传统方式会导致代码维护成本急剧增加。而Spring IOC容器则解决了这一问题:由IOC容器统一创建所有对象并管理对象间的依赖关系,开发者只需从容器中获取所需对象即可,无需关心对象的创建过程,彻底降低了代码耦合度。

一句话总结:IOC的核心价值是解耦,将对象的创建权从开发者反转给框架,实现代码的模块化与可维护性提升。

3.2 IOC容器的底层原理

Spring IOC容器的实现依赖于三大核心技术,缺一不可:

  1. DOM4J:用于解析XML格式的配置文件,获取配置中定义的bean信息(如类的全路径名、属性等)。

  2. 工厂模式 :通过工厂类统一创建对象,替代手动new操作,降低对象创建与使用的耦合度。

  3. 反射机制:根据XML配置中获取的类全路径名,通过Java反射机制动态创建对象,实现对象创建的灵活性。

IOC容器的核心工作流程(简化版)如下:

  1. 配置阶段 :开发者在XML配置文件中通过<bean>标签定义需要Spring管理的对象,如:<bean id="demo" class="com.qcby.service.Demo" />

  2. 解析阶段 :Spring容器启动时,通过DOM4J解析XML配置文件,获取beanidclass属性(类的全路径名)。

  3. 工厂创建对象 :Spring内部通过工厂类(如BeanFactory),利用反射机制根据类全路径名创建对象。简化的工厂类实现如下:

java 复制代码
public class DemoFactory {
    //利用dom4j得到name所对应的value值(类全路径名)
    public static Demo getDemo() throws Exception {
        //通过DOM4J解析XML获取类全路径名
        String value = "com.xxx.service.Demo";
        //通过反射创建对象
        Class clazz = Class.forName(value);
        //返回创建的对象(默认调用无参构造方法)
        return (Demo) clazz.newInstance();
    }
}

通过以上流程,Spring容器即可完成对象的创建与管理,开发者只需调用工厂方法或容器API获取对象即可。

3.3 Spring IOC容器的两种实现方式

Spring提供了两种IOC容器的实现方式,均继承自BeanFactory接口,适用于不同的开发场景:

3.3.1 BeanFactory(基础容器)

BeanFactory是Spring IOC容器的最顶层接口,是Spring内部使用的核心接口,不推荐开发者直接使用。其核心特点是:懒加载 ------加载配置文件时不会立即创建对象,只有在调用getBean()方法获取对象时,才会创建对象。

这种方式的优势是节省内存资源,适用于资源有限的场景(如嵌入式设备),但由于对象创建时机较晚,无法提前发现配置错误(如类路径写错)。

3.3.2 ApplicationContext(增强容器)

ApplicationContextBeanFactory的子接口,提供了更强大的功能(如国际化支持、事件发布、资源访问等),是开发者最常用的IOC容器实现。其核心特点是:预加载 ------加载配置文件时会立即创建所有配置的singleton类型对象。

这种方式的优势是提前初始化对象,后续获取对象时速度更快,且能提前发现配置错误,适用于绝大多数企业级应用开发。常用的实现类有:

  • ClassPathXmlApplicationContext:加载类路径下的XML配置文件。

  • FileSystemXmlApplicationContext:加载本地文件系统中的XML配置文件。

  • AnnotationConfigApplicationContext:加载注解式配置类(纯注解开发场景)。

四、Bean的作用域

Bean的作用域定义了Spring IOC容器中Bean实例的创建方式与存活范围。通过在<bean>标签中设置scope属性,可指定Bean的作用域。Spring 5共提供6种作用域,其中最常用的是singletonprototype

4.1 核心作用域详解

4.1.1 singleton(单例模式)

singleton是Spring容器的默认作用域。当Bean的作用域为singleton时,Spring IOC容器中只会创建一个该Bean的共享实例,所有获取该Bean的请求都会返回同一个实例(对象地址相同)。

特点:对象在容器初始化时创建(预加载),生命周期与容器一致(容器关闭时对象销毁),适用于无状态对象(如工具类、服务层对象)。

配置方式(默认可省略):<bean id="demo" class="com.qcby.service.Demo" scope="singleton" />

4.1.2 prototype(原型模式)

若Bean的作用域为prototype,则Spring容器会在每次调用getBean()方法获取该Bean时,创建一个新的实例。每次获取的Bean实例都是独立的,对象地址不同。

特点:懒加载(容器初始化时不创建对象),对象的销毁由JVM垃圾回收机制负责(Spring容器不管理prototype Bean的销毁),适用于有状态对象(如请求级别的数据模型)。

配置方式:<bean id="demo" class="com.qcby.service.Demo" scope="prototype" />

4.1.3 其他作用域(Web场景专用)

除上述两种核心作用域外,Spring还提供4种适用于Web应用的作用域,仅在Web环境下生效:

  • request:每次HTTP请求创建一个新Bean,请求结束后Bean销毁。

  • session:每个HTTP Session创建一个新Bean,Session失效后Bean销毁。

  • application:整个Web应用共享一个Bean,应用启动时创建,应用停止时销毁。

  • websocket:每个WebSocket连接创建一个新Bean,连接关闭时Bean销毁。

五、Spring框架的Bean管理

Bean管理是Spring IOC容器的核心功能,指Spring对Bean的"创建对象"和"注入属性"两大操作的管理。Spring提供两种Bean管理方式:基于XML配置文件的方式和基于注解的方式。

5.1 基于XML配置文件的Bean管理

基于XML的方式是Spring早期的主流Bean管理方式,通过XML配置文件定义Bean的创建规则与属性注入规则,适用于复杂的配置场景。

5.1.1 基于XML创建Bean对象

通过<bean>标签即可完成Bean对象的创建,核心配置如下:

XML 复制代码
<bean id="demo" class="com.xxx.service.Demo" />

关键说明:

  • id:Bean的唯一标识符,用于在容器中定位Bean(不可重复)。

  • class:Bean对应的类的全路径名,Spring通过该路径反射创建对象。

  • 创建对象的核心规则:Spring默认通过无参构造方法 创建Bean对象。若类中没有无参构造方法(仅定义了有参构造),且未在XML中指定构造方法参数,则会抛出NoSuchMethodException异常。

5.1.2 基于XML注入属性(DI依赖注入)

DI(Dependency Injection,依赖注入)是IOC的具体体现,指Spring容器在创建Bean对象时,自动将依赖的属性值或其他Bean对象注入到当前Bean中。常用的注入方式有两种:set方法注入和构造方法注入。

1. set方法注入(最常用)

set方法注入要求Bean类中为需要注入的属性提供对应的setter方法,Spring容器通过反射调用setter方法完成属性注入。支持注入普通类型、引用类型、数组、集合等多种数据类型。

(1)注入普通类型与引用类型

创建User类,定义属性并提供setter方法:

java 复制代码
public class User {
    private int age;
    private String name;
    private Demo demo;

    // 为每个属性提供setter方法
    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setDemo(Demo demo) {
        this.demo = demo;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", demo=" + demo +
                '}';
    }
}

在XML配置文件中通过<property>标签完成注入:

XML 复制代码
<!--配置Demo Bean-->
<bean id="demo" class="com.xxx.service.Demo" />

<!--配置User Bean并注入属性-->
<bean id="user" class="com.xxx.service.User" >
    <!--注入普通类型:name=属性名,value=属性值-->
    <property name="age" value="18"></property>
    <property name="name" value="张三"></property>
    <!--注入引用类型:ref=依赖的Bean的id-->
    <property name="demo" ref="demo"></property>
</bean>

测试代码:

java 复制代码
@Test
public void run1(){
    //创建Spring容器,加载配置文件
    ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
    //获取User对象
    User user = ac.getBean("user", User.class);
    //输出结果:User{age=18, name='张三', demo=com.qcby.service.Demo@xxx}
    System.out.println(user.toString());
}

(2)注入数组、List、Map等集合类型

创建CollectionBean类,定义集合属性并提供setter方法:

java 复制代码
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class CollectionBean {
    private String [] strs;
    private List<String> list;
    private Map<String,String> map;

    // 提供setter方法
    public void setStrs(String[] strs) {
        this.strs = strs;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "CollectionBean{" +
                "strs=" + Arrays.toString(strs) +
                ", list=" + list +
                ", map=" + map +
                '}';
    }
}

在XML配置文件中通过对应集合标签完成注入:

XML 复制代码
<bean id="collectionBean" class="com.xxx.service.CollectionBean">
    <!--注入数组:使用<array>标签-->
    <property name="strs">
        <array>
            <value>美美</value>
            <value>小凤</value>
        </array>
    </property>
    <!--注入List:使用<list>标签-->
    <property name="list">
        <list>
            <value>熊大</value>
            <value>熊二</value>
        </list>
    </property>
    <!--注入Map:使用<map>标签,entry对应键值对-->
    <property name="map">
        <map>
            <entry key="aaa" value="老王"/>
            <entry key="bbb" value="小王"/>
        </map>
    </property>
</bean>
2. 构造方法注入

构造方法注入通过Bean类的有参构造方法完成属性注入,无需提供setter方法。适用于属性必须初始化的场景(如创建对象时必须指定核心属性)。

创建Car类,定义有参构造方法:

java 复制代码
public class Car {
    private String cname;
    private Double money;

    // 有参构造方法(无参构造可省略,但若存在其他有参构造,建议显式定义)
    public Car(String cname, Double money){
        this.cname = cname;
        this.money = money;
    }

    @Override
    public String toString() {
        return "Car{" +
                "cname='" + cname + '\'' +
                ", money=" + money +
                '}';
    }
}

在XML配置文件中通过<constructor-arg>标签完成注入:

XML 复制代码
<bean id="car" class="com.xxx.service.Car">
    <!--name=构造方法参数名,value=参数值-->
    <constructor-arg name="cname" value="奔驰"></constructor-arg>
    <constructor-arg name="money" value="35"></constructor-arg>
</bean>

测试代码:

java 复制代码
@Test
public void run(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
    Car car = ac.getBean("car", Car.class);
    //输出结果:Car{cname='奔驰', money=35.0}
    System.out.println(car.toString());
}

同理,集合类型也可通过构造方法注入,只需在<constructor-arg>标签内部嵌套集合标签(<array><list><map>等)即可。

5.2 基于注解的Bean管理

基于注解的Bean管理是Spring后期推出的简化方案,通过在Java类、方法、属性上添加注解,替代XML配置文件的繁琐配置,大幅提升开发效率。

5.2.1 核心注解说明

Spring提供以下核心注解用于Bean管理:

1. 用于创建Bean对象的注解(替代<bean>标签)
  • @Component:通用注解,用于标识普通类为Spring管理的Bean。

  • @Controller:专门用于标识表现层(Controller)类,语义化注解,功能与@Component一致。

  • @Service:专门用于标识业务层(Service)类,语义化注解。

  • @Repository:专门用于标识持久层(Dao)类,语义化注解。

说明:以上四个注解功能完全一致,均可创建Bean实例。默认Bean的id为类名首字母小写(如UserServiceImpl对应的iduserServiceImpl),也可通过注解的value属性自定义id(如@Controller(value="us"))。

2. 用于注入属性的注解(替代<property>标签)
  • @Value:用于注入普通类型(String、int、double等),直接指定属性值。

  • @Autowired:用于注入引用类型,默认按"类型匹配"自动装配(即查找容器中与属性类型一致的Bean)。

  • @Qualifier:与@Autowired搭配使用,强制按"名称匹配"自动装配(需指定Bean的id),不能单独使用。

  • @Resource:Java原生注解(JSR-250规范),Spring支持该注解,默认按"名称匹配"自动装配(通过name属性指定Bean的id),无name属性时按类型匹配。

5.2.2 基于注解创建Bean对象

步骤1:编写接口与实现类,在实现类上添加创建Bean的注解。

java 复制代码
// 接口
package com.xxx.testanno;
public interface UserService {
    public void hello();
}

// 实现类,添加@Controller注解交由Spring管理
package com.xxx.testanno;
import org.springframework.stereotype.Controller;

// 自定义Bean的id为"us"
@Controller(value="us")
public class UserServiceImpl implements UserService {
    public void hello() {
        System.out.println("使用注解,方便吧!");
    }
}

步骤2:编写Spring配置文件,开启注解扫描(关键步骤)。

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" 
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
   
    <!--开启注解扫描:扫描com.qcby包下所有类的注解-->
    <context:component-scan base-package="com.qcby"/>
</beans>

步骤3:编写测试类。

java 复制代码
package com.xxx.test;
import com.xxx.testanno.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo2 {
    @Test
    public void run1(){
        //加载Spring配置文件,启动容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContextanno.xml");
        //按id获取Bean对象
        UserService us = (UserService) ac.getBean("us");
        //调用方法,输出:使用注解,方便吧!
        us.hello();
    }
}

5.2.3 基于注解注入属性

Car类和Person类为例,演示注解注入属性的用法:

java 复制代码
// Person类
package com.xxx.testanno;
import org.springframework.stereotype.Controller;
import org.springframework.beans.factory.annotation.Value;

@Controller
public class Person {
    // 注入普通类型:直接指定属性值
    @Value("张三")
    private String pname;

    @Override
    public String toString() {
        return "Person{" +
                "pname='" + pname + '\'' +
                '}';
    }
}

// Car类
package com.xxx.testanno;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

// 自定义Bean的id为"c"
@Component(value = "c")
public class Car {
    // 注入普通类型:value属性可省略(仅当注解只有value一个属性时)
    @Value("大奔2")
    private String cname;
    @Value(value = "400000")
    private Double money;

    // 注入引用类型:按类型自动装配Person对象
    @Autowired
    // 若存在多个Person类型的Bean,可通过@Qualifier指定id:@Qualifier(value = "person")
    // 也可使用@Resource(name = "person")按名称装配

    private Person person;

    @Override
    public String toString() {
        return "Car{" +
                "cname='" + cname + '\'' +
                ", money=" + money +
                ", person=" + person +
                '}';
    }
}

测试代码:

java 复制代码
@Test
public void run1(){
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    //获取Car对象
    Car car = (Car) ac.getBean("c");
    //输出结果:Car{cname='大奔2', money=400000.0, person=Person{pname='张三'}}
    System.out.println(car);
}

关键说明:使用注解注入属性时,无需为属性提供setter方法,Spring通过反射直接为属性赋值,简化了代码编写。

5.3 纯注解开发(无XML配置)

纯注解开发是Spring Boot的核心开发方式,完全摒弃XML配置文件,通过"配置类+注解"实现所有Bean管理功能。核心是使用@Configuration注解标识配置类,替代applicationContext.xml文件。

1. 核心注解
  • @Configuration:标识当前类为Spring的配置类,替代XML配置文件。

  • @ComponentScan:开启注解扫描,替代XML中的<context:component-scan>标签,通过value属性指定扫描的包路径。

2. 纯注解开发实战

步骤1:编写实体类Order

java 复制代码
package com.xxx.demo4;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Order {
    @Value("北京")
    private String address;

    @Override
    public String toString() {
        return "Order{" +
                "address='" + address + '\'' +
                '}';
    }
}

步骤2:编写配置类SpringConfig

java 复制代码
package com.xxx.demo4;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

// 标识为配置类
@Configuration
// 开启注解扫描,扫描com.qcby包下所有类
@ComponentScan(value = "com.qcby")
public class SpringConfig {
}

步骤3:编写测试类(使用AnnotationConfigApplicationContext加载配置类)。

java 复制代码
package com.xxx.test;
import com.qcby.demo4.Order;
import com.qcby.demo4.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Demo4 {
    @Test
    public void run(){
        // 加载配置类,启动Spring容器
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        // 获取Order对象
        Order order = (Order) ac.getBean("order");
        // 输出结果:Order{address='北京'}
        System.out.println(order);
    }
}

纯注解开发的优势:配置简洁、开发高效,是微服务架构的主流开发方式,也是Spring Boot和Spring Cloud的基础。

相关推荐
不知疲倦的仄仄3 小时前
第二天:深入理解 Selector:单线程高效管理多个 Channel
java·nio
期待のcode3 小时前
Java虚拟机栈
java·开发语言·jvm
珂朵莉MM3 小时前
全球校园人工智能算法精英大赛-产业命题赛-算法巅峰赛 2025年度画像
java·人工智能·算法·机器人
芒克芒克3 小时前
本地部署SpringBoot项目
java·spring boot·spring
cute_ming3 小时前
关于基于nodeMap重构DOM的最佳实践
java·javascript·重构
sww_10263 小时前
Netty原理分析
java·网络
小突突突4 小时前
Spring框架中的单例bean是线程安全的吗?
java·后端·spring
iso少年4 小时前
Go 语言并发编程核心与用法
开发语言·后端·golang
掘金码甲哥4 小时前
云原生算力平台的架构解读
后端
码事漫谈4 小时前
智谱AI从清华实验室到“全球大模型第一股”的六年征程
后端