SpringBoot——入门及原理

SpringBoot用来简化Spring应用开发,约定大于配置,去繁从简,是由Pivotal团队提供的全新框架。其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置(有特殊需求可以添加自己的配置覆盖默认配置),从而使开发人员不再需要定义样板化的配置。SpringBoot可以看成是J2EE的一站式解决方案。

一、SpringBoot 的优点

【1】快速创建独立运行的Spring项目以及与主流框架集成。
【2】使用嵌入式的Servlet容器,应用无需打成war包,可以打成jar包,通过java -jar的方式直接运行。
【3】starters(启动器)自动依赖与版本控制。
【4】大量的自动配置,简化开发,也可以修改默认值。
【5】无需配置XML,无代码生成,开箱即用。
【6】准生产环境的运行时应用监控。
【7】与云计算的天然集成。

二、解决微服务部署和运维难的问题:Spring Boot

 如上的流程依次为: 搭建项目 构建连接 批处理

三、Spring Boot 入门项目

HelloWorld(也可以参考五,快速创建一个 SpringBoot项目)

【1】准备环境:Mavensettings.xml配置文件的profiles标签添加如下信息:

<profile>
<id>jdk-1.8</id>
<activation>
    <activeByDefault>true</activeByDefault>
    <jdk>1.8</jdk>
</activation>
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>

【2】将IDEAMaven更换为我们自己本地安装的Maven。(自行百度更换)创建一个maven工程[jar],在pom.xml中导入如下依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

【3】编写一个主程序,启动SpringBoot应用

@SpringBootApplication
public class Hello {
   public static void main(String[] args) throws Exception {
       //启动spring应用
       SpringApplication.run(Hello.class, args);
   }
}

【4】编写相关的ControllerService

@Controller
public class HelloController {
   @ResponseBody
   @RequestMapping("/hello")
   public String hello(){
       return "hello world!";
   }
}

【5】运行主测试程序。简化部署应用<可以将应用打包成一个可执行的jar包>:通过Maven Projects中 的package(双击)即可。生成jar的位置:默认在项目的target目录下的“项目名称.jar”文件。运行jar:在命令行可以通过 “java -jar jar文件名.jar” 命令运行项目。

<build>
   <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
   </plugins>
</build>

四、Hello World 探究(POM文件)

【1】父项目[spring-boot-starter-parent]:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
</parent>

【2】进入spring-boot-starter-parent发现它还有一个父项目 :

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
</parent>

【3】进入spring-boot-dependencies后,发现如下信息,与之前我们创建的分布式项目继承的Maven父项目功能是一样的,用来管理所有jar包依赖的版本。称为SpringBoot的版本仲裁中心,以后我们导入依赖默认是不需要写版本;(没有在dependencies里面管理的依赖,需要声明版本号)

<properties>
    <activemq.version>5.15.3</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.62</appengine-sdk.version>
    <artemis.version>2.4.0</artemis.version>
    <aspectj.version>1.8.13</aspectj.version>
    <assertj.version>3.9.1</assertj.version>
    <... 此处省略 .../>
</properties>

【4】启动器[spring-boot-starter-web]

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring-boot-starter-webspring-boot-starterspring-boot场景启动器;进入官网可以到有许多场景启动器,简单点说就是通过此功能将相关jar包给组合在起来,我们使用时只需要引入一个Web Starter就可以轻松搞定。Spring Boot将所有的功能场景都抽取出来,做成一个个的 starters(启动器),只需要在项目里面引入这些starter相关场景,所有依赖都会导入进来。要用什么功能就导入什么场景启动器。

点击web右边的pom可以看到SpringBoot为我们依赖的其它jar包,帮我们导入了web模块正常运行所依赖的所有组件。如下:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
</dependencies>

【5】主程序类(Java类):@SpringBootApplication:此注解声明的类,是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot

//@ImportResource(locations={"classpath:bean.xml"})
//@SpringBootApplication 来标注一个主程序类,说明这是一个SpringBoot应用
@SpringBootApplication
public class HellowordQuickStartApplication {

    public static void main(String[] args) {
        /*SpringBoot应用启动项
        HellowordQuickStartApplication.class 参数必须是用@SpringBootApplication注解修饰的类
        */
        SpringApplication.run(HellowordQuickStartApplication.class, args);
    }
}

@SpringBootApplication(主要由:@SpringBootConfiguration/@EnableAutoConfiguration/@ComponentScan组成)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
       @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
       @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

@SpringBootConfiguration:标注在某个类上,表示此类是一个SpringBoot的配置类。由以下注解组合形成:配置类 == 配置文件,配置类也是容器的一个组件,底层由@Component等等组成。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration //表示此类是一个配置类  是spring的一个组件
public @interface SpringBootConfiguration {

@EnableAutoConfiguration:开启自动配置功能。也是一个组合注解,由以下注解组成(部分重要注解):

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

@AutoConfigurationPackage:自动依赖相关的配置包,也是一个组合注解,主要由@import等注解组合

@Import({Registrar.class})//给容器中导入一个组件;导入的组件由此组建决定。
public @interface AutoConfigurationPackage {

进入@Import(Registrar.class)中的Registrar类中,通过断点,可以查看到我注释的一些信息。

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    Registrar() {
    }
    //registerBeanDefinitions方法中的metadata可以查看到我们启动类使用的注解 @SpringBootApplication
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        AutoConfigurationPackages.register(registry, new String[]{(new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()});
    }
    //new AutoConfigurationPackages.PackageImport(metadata) 可以解析出我们当前主启动所在的package包
    public Set<Object> determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
    }
}

@Import(Registrar.class)作用:将主配置类的所在包以及下边所有子包里面的所有组件扫描到Spring容器中。这也就能理解为什么会自动扫描我们写的@Controller类了。

@Import(AutoConfigurationImportSelector.class):进入AutoConfigurationImportSelector.class类中,查看如下方法:

public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if(!this.isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    } else {
        try {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            // 主要用到的是 这个 configurations 后面会有重点说明
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            configurations = this.sort(configurations, autoConfigurationMetadata);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.filter(configurations, autoConfigurationMetadata);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return StringUtils.toStringArray(configurations);
        } catch (IOException var6) {
            throw new IllegalStateException(var6);
        }
    }
}

这是导入组件的选择器方法,将所有需要导入的组件以全类名的方式返回,这些组件最终被添加到容器中。其中List<String> configurations会给容器中导入非常多的自动配置类[xxxAutoConfiguration],就是给容器中导入这个场景需要的所有组件,并配置好这些组件。有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;自动配置类共109个,如下部分所示:

☹ 那么我们就有疑问,这些自动配置类都是从哪里来的?
进入这个方法:this.getCandidateConfigurations(annotationMetadata, attributes)

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // *** 后边需要了解的方法 ***
    //SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

进入SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader)方法,具体注释说明:

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
    //org.springframework.context.ApplicationContextInitializer
    String factoryClassName = factoryClass.getName();
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
    if(result != null) {
        return result;
    } else {
        try {
            //通过类加载器(classLoader获取)META-INF/spring.factories(也就是配置了109个自动配置类的文件) 资源
            Enumeration<URL> urls = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");
            LinkedMultiValueMap result = new LinkedMultiValueMap();

            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                UrlResource resource = new UrlResource(url);
                //将urls 当做一个properties配置文件
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                Iterator var6 = properties.entrySet().iterator();

                while(var6.hasNext()) {
                    Entry<?, ?> entry = (Entry)var6.next();
                    //将META-INF/spring.factories文件中的EnableAutoConfiguration下的配置进行加载   如下图所示
                    List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));
                    result.addAll((String)entry.getKey(), factoryClassNames);
                }
            }

            cache.put(classLoader, result);
            return result;
        } catch (IOException var9) {
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var9);
        }
    }
}

我们进入其中一个自动配置类中看看SpringBoot是不是真的帮我们已经配置好了一些属性[WebMvcAutoConfiguration]:

//这里我就摘出一些重要的配置,来帮我我们观察即可。
@Configuration
public class WebMvcAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    /** 视图解析器 , SpringBoot中的所有配置文件都是.java形式,方法的名字,就是以前xml中的id。
        等等都是用注解表示的,这个我们后面会重点说明,这里就先了解一下*/
    //我们可以看到SpringBoot已经帮我们配置好了视图解析器 等等一些功能 我们直接使用就好
    public InternalResourceViewResolver defaultViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix(this.mvcProperties.getView().getPrefix());
        resolver.setSuffix(this.mvcProperties.getView().getSuffix());
        return resolver;
    }
}

总结: SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。如此一来,就具有我们在SSM等环境下写了一大堆配置文件后才具有的功能。而这些所有配置文件都在spring-boot-autoconfigure-2.0.0.RELEASE.jar 中。

五、使用 Spring Initializer 快速创建 Spring Boot 项目

注意:Artifact中不能大小写混合使用。

通过需求选择starts,例如选择Web

我们就会发现pom.xml文件中,就会自动配置了我们引入的starts

<!-- 摘取一部分 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

添加controller层: 新注解@RestController == @ResponseBody@Controller的合体;

//这个类的所有方法返回的数据直接写给浏览器(如果是对象转为JSON)
//@ResponseBody@Controller
@RestController
public class HelloWordController {
    @RequestMapping("/hello")
    public String hello(){
        return "hell";
    }
}

优点: 默认生成的SpringBoot项目,我们只需要编写自己的逻辑。默认生成的Resources配置文件的目录结构:
【1】static:保存所有的静态资源。 [js/css/image]
【2】templates:保存所有的模板页面[SpringBoot默认jar包使用嵌入式的 Tomcat,默认不支持JSP页面]但可以使用模板引擎。(freemarkerthymeleaf
【3】application.propertiesSpringBoot应用的配置文件。默认的配置都在此文件可以修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/165252.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

本地Git项目同时推送至GitHub和Gitee

分别在gitee和github新建一个仓库 github: gitee: 添加远程仓库 git remote add origin1 [你的GitHub仓库URL] git remote add origin2 [你的Gitee仓库URL] 在本地中初始化创建一个git本地分支 git init 进入.git目录下修改config文件 [remote "origin"] url g…

ubuntu安装完qt后发现找不到图标

layout: post # 使用的布局&#xff08;不需要改&#xff09; title: Qt启动问题 # 标题 subtitle: ubuntu安装完Qt #副标题 date: 2023-11-18 # 时间 author: BY ThreeStones1029 # 作者 header-img: img/about_bg.jpg #这篇文章标题背景图片 catalog: true # 是否归档 tags: …

Unity 场景烘培 ——unity Post-Processing后处理1(四)

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、Post-Processing是什么&#xff1f;二、安装使用Post-Processing1.安装Post-Processing2.使用Post-Processing&#xff08;1&#xff09;.添加Post-process Volume&#xff08…

mfc140.dll是什么文件?如何修复mfc140.dll丢失的方法分享

​mfc140.dll丢失的原因 未正确安装Microsoft Visual C Redistributable&#xff1a;mfc140.dll是Visual C库的一部分&#xff0c;如果没有正确安装Visual C Redistributable&#xff0c;可能导致mfc140.dll丢失。 系统文件损坏&#xff1a;由于病毒感染、系统错误或其他原因…

车载通信架构 —— 新车载总线类型下(以太网)的通信架构

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

python表白弹框

# codinggbk import tkinter as tk import random# 创建主窗口并隐藏 root tk.Tk() root.attributes(-alpha, 0) # 设置主窗口为不可见# 表白内容 message "cnmsb"# 创建弹框函数 def create_popup():x random.randint(0, root.winfo_screenwidth()) # 随机生成…

Kafka-4.1-工作原理综述

1 Kafka工作原理详解 1.1 工作流程 Kafka集群将 Record 流存储在称为 Topic 的类中&#xff0c;每个记录由⼀个键、⼀个值和⼀个时间戳组成。 Kafka 中消息是以 Topic 进⾏分类的&#xff0c;⽣产者⽣产消息&#xff0c;消费者消费消息&#xff0c;⾯向的都是同⼀个Topic。Topi…

Python武器库开发-flask篇之session与cookie(二十六)

flask篇之session与cookie(二十六) 在 Flask 中&#xff0c;可以使用 session 来在不同请求之间存储和传递数据。Session 在客户端和服务器端之间交换&#xff0c;但是数据存储在服务器端。 Session 与 Cookie 的区别 session 和 cookie 都可以用来在不同请求之间存储和传递…

麦克风阵列入门

文章引注&#xff1a; http://t.csdnimg.cn/QP7uC 一、麦克风阵列的定义 所谓麦克风阵列其实就是一个声音采集的系统&#xff0c;该系统使用多个麦克风采集来自于不同空间方向的声音。麦克风按照指定要求排列后&#xff0c;加上相应的算法&#xff08;排列算法&#xff09;就可…

STM32串口重定向/实现不定长数据接收

STM32串口重定向/实现不定长数据接收 重定向MicroLIB 不定长数据接收 这是一期STM32内容代码分享&#xff0c;关于STM32重定向的代码和一些出现的问题吗&#xff0c;以及串口接收不定长数据思路 重定向 重定向的功能&#xff1a;能够在STM32中使用printf函数通过串口发送数据 …

常见树种(贵州省):001松类

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、华山松…

【评估分级方法】自然断点法(Python实现全代码)

自然断点法 自然断点法有两个称呼&#xff0c;一个就是直接英文名称&#xff0c;叫做“Natural Breaks”&#xff0c;这就不解释了&#xff0c;还有一个称呼就是ArcGIS里面用的&#xff0c;叫做“Jenks”&#xff0c;主要是来源于它的创造者&#xff1a;乔治弗雷德里克詹克斯&…

中间件安全: Apache 远程代码执行 (CVE-2021-42013)

中间件安全&#xff1a; Apache 远程代码执行 &#xff08;CVE-2021-42013&#xff09; Apache HTTP Server是美国阿帕奇&#xff08;Apache&#xff09;基金会的一款开源网页服务器。该服务器具有快速、可靠且可通过简单的API进行扩充的特点&#xff0c;发现 Apache HTTP Ser…

ComText让机器人有了情节记忆

为了让人类与机器人更好地交流&#xff0c;MIT 计算机科学与人工智能实验室的研究员开发了一个名为 ComText 的程序。这款程序给机器人增加了情节记忆&#xff0c;让它们能够接受更加复杂的命令。目前&#xff0c;他们已经在机器人 Baxter 上测试了程序。 机器人没有情景化的记…

Java,集合框架,关于Map接口与Collections工具类

目录 Map接口 Map及其实现类的对比&#xff1a; HashMap中元素的特点&#xff1a; 相关方法&#xff1a; 添加、修改操作: 删除操作&#xff1a; 元素查询的操作: 元视图操作的方法&#xff1a; TreeMap的使用&#xff1a; Properties类&#xff1a; Collections工具…

2023上海初中生古诗文大会复赛12月2日举行,关键事项为您划重点

今天中午12点&#xff0c;古诗文大会官微发布消息&#xff1a;2023上海中学生古诗文大会&#xff08;初中组&#xff09;复选将于12月2日举行。 具体安排和注意事项、常见问题&#xff0c;六分成长为您整理如下。 一、2023年初中生古诗文大会复赛日期和时间 12月2日&#xff…

前端调试只会console.log()?

前言 相信大家在日常开发中调试代码是必不可少的步骤&#xff0c;毕竟谁也不能保证代码不出问题&#xff0c;总得debug一下&#xff0c;输出信息看看数据有没有问题。是不是习惯性console.log(‘XXX’)或者debugger呢。而JavaScript中的console对象提供了丰富的方法用于更灵活…

学生邮箱白嫖/免费安装JetBrains全家桶(IDEA/pycharm等) —— 保姆级教程

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信您对博主首页也很感兴趣o (ˉ▽ˉ&#xff1b;) 博主首页&#xff0c;更多redis、java等优质好文以及各种保姆级教程等您挖掘&#xff01; 目录 前言 JetBrains全家桶介绍 申请过程&#xff1a; 获取学…

AIGC ChatGPT4 读取接口文件并进行可视化分析

数据分析的过程中,对数据文件进行可视化分析是每个数据分析师必备的技能。如下图数据源。 现在需要对各地区的销量进行汇总,使用Python来进行分析。 但是又不想写代码,或者不会Python代码,可以用ChatGPT4来帮我们完成代码的编写。 完整的Python代码: import pandas as p…

【装机】第一次装机记录

本篇文章记录第一次装机的过程。 配置 部件型号CPUAMD 锐龙 R5 7500F主板华硕 TUF GAMING A620M-PLUS显卡耕升 RTX4070 踏雪内存金百达 黑刃 DDR5 16G/32G 6000硬盘铠侠 2TB EXCERIA Pro SE10 极至超速系列电源微星 MAG A650BN散热利民 AX120 R SE AGHP逆重力热管支持LGA1700…
最新文章