Spring中Bean对象的存储与读取

news2024/11/24 9:13:03

创建 Maven 项目

在这里插入图片描述

添加 Spring 框架支持

在项目的 pom.xml 中添加 Spring 支持
如何选定版本环境:打开官网,点击github图标
在这里插入图片描述
jdk8最后一个Spring版本是5.3.x,Spring6.0.x最低需要jdk17
在这里插入图片描述

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.31</version>
        </dependency>
</dependencies>

在这里插入图片描述

版本冲突问题Maven自己处理
version : 可以选择带有 RELEASE结尾或者纯数字结尾,这样的版本更稳定

添加一个启动类

项目下创建一个main方法的启动类
在这里插入图片描述

存储 Bean 对象

  1. 存储 Bean 之前,要先有 Bean 才行
    在这里插入图片描述
  2. 将创建的 Bean 注册到 Spring 容器中
    这里并非实际意义上的存储,而是类似于交给 IoC 容器进行托管
    在这里插入图片描述
    在 resources 目录下添加 spring-config.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">
</beans>
  1. 从 Spring 中取出 bean 对象
    取 bean 需要先得到 Spring 对象(Spring上下文)
    在这里插入图片描述
    获取并使用 Bean 对象,分为以下3步
  • 获取Spring上下文
  • 上下文获取 Bean
  • 使用 Bean

如果获取多个 Bean 的话,重复以上2,3步骤

两种方式获取Spring 上下文对比

Spring 上下文可以使用 ApplicationContext 或者 BeanFactory获取

ApplicationContext顶层接口

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

在这里插入图片描述

BeanFactory顶层接口

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

在这里插入图片描述
继承关系
在这里插入图片描述
ApplicationContext 和 BeanFactory 效果是一样的,BeanFactory 属于 ApplicationContext 子类,它们区别如下

  • 继承角度:Spring 容器有两个顶级接口:BeanFactory 和 ApplicationContext

  • 其中 BeanFactory 提供了基础的访问容器的能力,而 ApplicationContext 属于 BeanFactory 的子类,除了 BeanFactory 的所有功能外,它还拥有独特的特性,添加了对国际化的支持、资源访问的支持、以及事件传播等方面的支持

  • 性能角度:ApplicationContext 是一次性加载并初始化所有的 Bean 对象「更方便」;BeanFactory 是按需加载并初始化「更轻量」

    ClassPathXmlApplicationContext 属于 ApplicationContext 的子类,拥有 ApplicationContext 的所有功能是通过 xml 的配置来获取所有的 Bean 容器的

获取指定的 Bean 对象

ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
        User user = (User) context.getBean("user");
        user.sayHi();
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("Spring-config.xml"));
        User user1 = (User) beanFactory.getBean("user");
        user1.sayHi();


// 运行结果
你好
你好

注意事项

Bean 的 id 要一一对应

<beans>
        <bean id="user" class="Beans.User"></bean>
</beans>
User user = (User) context.getBean("user");
User user1 = (User) beanFactory.getBean("user");

getBean 方法的更多用法

getBean() 方法很多重载,我们也可以使用其他方法来获取 Bean 对象

先看一下 getBean() 源码

在这里插入图片描述

getBean(String, Class): 先根据 id 匹配,再根据Class匹配

当有两个相同 id 的时候利用此方法查询会 报错Nouni

get(Class, String): 先根据Class匹配,再根据 id 匹配

当有两个的Bean,利用此方法,则会 报错Nouni

ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
User user = context.getBean(User.class);

User user1 = context.getBean("user1", User.class);

二者的区别

当有多个重复的对象被注册到 Bean 中的时候,只能通过 id属性 来获取

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XwSPGiLV-1651373641288)(/Users/cxf/Desktop/MarkDown/images/注册重复的Bean.png)]

<beans>
        <bean id="user" class="Beans.User"></bean>
        <bean id="user1" class="Beans.User"></bean>
        <bean id="user2" class="Beans.User"></bean>
</beans>

如果继续使用 context.getBean(User.class) 就会报错。应该搭配 id 一起使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bxQ95tb6-1651373641288)(/Users/cxf/Desktop/MarkDown/images/注册重复的Bean报错.png)]

总结Spring使用流程

  1. 操作容器之前,先要有容器
  2. 存对象
    1. 创建 Bean「普通类」
    2. 将 Bean 注册「配置」到 Spring-config.xml 中
  3. 取对象
    1. 得到 Spring 上下文,并读取到 Spring 的配置文件
    2. 获取某一个 Bean 对象
    3. 使用 Bean 对象
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R9uFOUgn-1651373641289)(/Users/cxf/Desktop/MarkDown/images/使用流程.png)]

配置扫描路径配合注解进行存储Bean对象

在上述操作过程中,我们发现存储对象并没有想象中的那么 简单,所以就有了更简单的操作 Bean对象 的方法
Spring 更简单的存储对象和读取对象核心是使用注解

之前我们还需要在 Spring 的配置文件 spring-config.xml 中添加一行 bean 注册内容才行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WEAR2KLN-1651373641289)(/Users/cxf/Desktop/MarkDown/images/注册重复的Bean.png)]

因此 Spring 中为了方便注册,我们只需要配置一个存储对象的扫描包即可「目录中的所有 Bean 被添加注解后都会被注册到 Spring 容器中」

配置扫描路径代码模板

<?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:content="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 https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="/Beans"></content:component-scan>
</beans>

对比之前的 Spring-config.xml 发现多了标红的两行,这两行就是注册扫描的包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dzz9lltK-1651373641290)(/Users/cxf/Desktop/MarkDown/images/注册扫描的包.png)]

也就是说,即使添加了注解,如果不是在配置的扫描报下的类对象,也是不能被存储的 Spring 中的

五大类注解

想把扫描包中的 Bean 添加到 Spring,由两类注解类型可以实现

  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. 方法注解:@Bean「必须结合类注解才能起效」

这么多注解的原因

我们发现它们的功能是一样的,都能达到 添加注解注册Bean 的功能,那么为何还要有这么多注解类型呢?

这就和每个省市都有自己的车牌号一样。全国的各个地区买的相同类型的车都是一样的,但是车牌号却不同:湖北的车有鄂A:武汉的车;鄂B:黄石的车;鄂C:十堰的车。。。这样做的好处就是节约了车牌号以外还可以查看车辆的归属地方便车管局管理。

那么为什么需要这么多的类注解也是一样的原因,就是让程序员看到类注解之后就能直接了解当前类的用途

  • @Controller:业务逻辑层
  • @Service:服务层
  • @Repository:持久层
  • @Configuration:配置层

程序的工程分层调用流程如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZnBODXy0-1651373641291)(/Users/cxf/Desktop/MarkDown/images/程序的工程分层调用.png)]

@Component是其它注解的父类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TpHIUISM-1651373641291)(/Users/cxf/Desktop/MarkDown/images/类注解之间的关系.png)]
发现这 4个 注解里都有一个注解 @Component,说明他们本身就是属于 @Component子类

在看 @Component的源码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-We6k8uwI-1651373641292)(/Users/cxf/Desktop/MarkDown/images/@Component的源码.png)]
源码溯源就到此为止了,只需要了解它们四个实现了@Component接口即可

Bean 的命名源码

通过注解注册的bean名称有自己的一套默认规则:

  1. 第一第二首字母是大写的话就是原类名
  2. 其余是小驼峰方式命名
    在这里插入图片描述
public static String decapitalize(String name) {
    if (name == null || name.length() == 0) {
        return name;
    }
  	// 如果类名长度大于1,并且前俩字母都是大写就直接返回原类名
    if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
            Character.isUpperCase(name.charAt(0))) {
        return name;
    }
  	// 否则就是将首字母小写再返回
    char chars[] = name.toCharArray();
    chars[0] = Character.toLowerCase(chars[0]);
    return new String(chars);
}

方法注解

类注解是添加到某个类上的,而方法注解是放到某个方法上的

@Bean要搭配类注解一起使用才可以将方法存储到 Spring 中

model层

package app.model;

public class User {
    private Integer id;
    private String userName;
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

service层

package app.service;

import app.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void doUserService() {
        System.out.println("doUserService.");
    }

    public User getUser() {
        User user = new User();
        user.setId(1);
        user.setUserName("张三");
        user.setAge(18);
        return user;
    }
}

controller层

package app.controller;

import app.model.User;
import app.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

// 也可以通过 xml 中 bean 标签注册
@Controller
public class UserController {
	@Autowired
    private UserService userService;

    public void doUserController() {
        System.out.println("doUserController.");
    }

	@Bean
    public User getUser() {
        return userService.getUser();
    }
}

获取@Bean对象:bean名称采取的是方法名而非类名

// 1.获取 Spring 上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
// @Bean方法注解
User user = beanFactory.getBean("getUser", User.class);

重命名 Bean

同一项目下类名一般不会出现重复但方法名有意外情况

  1. 不同类名出现同一个方法名
    在这里插入图片描述
  2. 同一类中出现方法重载
    此时如果调用会报错,因为@Bean注解无法添加参数

查看 @Bean 源码会发现 name 是一个数组,因此可以填入很多bean的名称。但一般一个就够。
在这里插入图片描述
3种方式给Bean重命名。重命名之后就不能通过方法名获取Bean对象了
在这里插入图片描述

获取Bean对象(对象装配)

回顾之前在存储bean对象之后是如何获取的

  1. new
  2. 先得到Spring上下文,再通过getBean获取
  3. 更简单的获取方式:对象注入

这里就讲解一下对象注入
对象装配:获取 Bean 对象
对象注入:把对象取出来放在某个类中

对象注入有 3 种方法

  1. 属性注入
  2. 构造方法注入
  3. Setter注入

属性注入

@Autowired: 现根据类型查找再根据名称查找。所以bean的名称随意给都可以,这里按照标准给的是 userService
在这里插入图片描述
优点:写法简单
缺点:

  1. 功能缺陷:不支持final修饰
  2. 通用性问题:只适用于IoC容器,非IoC容器无法使用
  3. 更容易违背单一设计原则(因为使用简单,所以滥用风险更大)

Setter 注入

在这里插入图片描述
优点:符合单一设计原则
缺点:

  1. 功能缺陷:不能诸如一个不可变对象【不能被final修饰】
  2. 注入对象可能会被改变

构造方法注入

final不加也可以,对于专业版IDEA会提示进行final修饰
在这里插入图片描述
当当前类中只有一个构造方法的时候可以省略@Autowired
优点:

  1. 支持final修饰注入不可变对象
  2. 注入对象不会被更改
  3. 完全初始化
  4. 通用性更好

另外一种对象装配的关键字:@Resource

仅支持两种装配方式,不支持构造方法注入。用法和@Autowired一样

  1. 属性注入
  2. Setter注入

@Resource支持更多的参数【JDK自带】
在这里插入图片描述
经常用的是name参数,如果Spring中 @Bean 注解存储的Bean对象制定了名称,那么此时可以通过name属性用于指定获取对应名称的bean

同一个类型注入多个Bean对象
在这里插入图片描述
获取Bean对象的时候需要指定bean名称,否则会在运行时报错
在这里插入图片描述
此时因为是user1,@Autowired现根据type查找会发现有多个User类型的Bean对象然后再根据name查找就会获取到user1的bean对象
此时对于开发而言,user1这样的明明肯定不符合规定,因此需要一个修改一下bean的名字才行。所以引入了@Resource注解
在这里插入图片描述
但是@Resource注解由于不支持构造方法注入,如果仍然想用Spring的@Autowired注解使用构造方法注入就需要引入一个新注解解决名字的问题:@Qualifier
在这里插入图片描述

@Autowired VS @Resource

@Autowired@Resouce
来源来自Spring来自 JDK
使用时参数不同搭配@Qualifier获取指定名称bean支持更多的参数,可以设置 name 来获取指定 Bean
修饰对象不同修饰属性,构造方法,Setter修饰属性,Setter

Bean的生命周期

对象注入
在这里插入图片描述
对象获取
在这里插入图片描述
运行结果
在这里插入图片描述

修改前: Dog{id=1, name='旺财', age=1}
修改后: Dog{id=1, name='喵喵', age=1}
后续获取: Dog{id=1, name='喵喵', age=1}

会发现由于单例模式,导致公共的Bean对象被修改之后,后续获取的Bean都会被修改
因此就引入Bean的作用域【从之前的代码区域提升到现在框架区域】

  1. singleton: 单例
    Spring默认作用域,通常无状态的Bean使用该作用域

    无状态:表示该Bean对象的属性状态不需要更新

  2. prototype: 原型【多例】
    通常有状态的Bean使用该作用域
  3. request: 请求
    每次http请求会创建新的Bean,同一次http请求中创建的bean是同一个Bean【限定Spring MVC中使用】
  4. session: 会话
    同一个http session中创建的Bean是同一个Bean【限定Spring MVC中使用】
  5. application: 全局
    在同一个Spring上下文中创建的Bean是同一个Bean【限定Spring MVC中使用】
  6. websocket: HTTP WebSocket作用域
    在一个WebSocket的生命周期中创建的Bean是同一个Bean【限定Spring WebSocket中使用】

设置的方式有两种
在这里插入图片描述
此时运行结果

修改前: Dog{id=1, name='旺财', age=1}
修改后: Dog{id=1, name='喵喵', age=1}
后续获取: Dog{id=1, name='旺财', age=1}

Bean的生命周期

  1. 实例化【≠初始化,仅仅是分配内存空间】
  2. 设置属性【DI依赖注入】
  3. 初始化
    • 执行各种通知
    • 初始化的前置方法
      xml:义init-method
      注解:@PostConstruct注解
    • 初始化方法
    • 初始化后置方法
  4. 使用Bean
  5. 销毁Bean

会发现注解的执行顺序先于xml

Spring 主要执行流程

  1. 启动容器
    在这里插入图片描述
  2. Bean初始化
    配置文件中的扫描路径,扫描路径下的类
    在这里插入图片描述
  3. 注入Bean
    扫描路径下将带有5大类注解的类添加进Spring IoC容器中
  4. 使用Bean
    @Bean、@Autowired、@Resource注解将对应的方法、类成员进行装配
  5. 销毁Bean
  6. 关闭容器

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QT upd测试

QT upd测试 本次测试将服务器和客户端写在了一个工程下&#xff0c;代码如下 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QUdpSocket> #include<QTimer>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE…

Windows下RocketMQ搭建

RocketMQ安装 注&#xff1a;Windows必须先安装64bit的 JDK1.8 或以上版本及Maven 。 1.官网下载&#xff1a;下载 | RocketMQ 2.将下载下的安装文件解压到本地磁盘 3.配置环境变量 &#xff1a; 变量名&#xff1a;ROCKETMQ_HOME 变量值&#xff1a;G:\RocketMQ\rocketmq…

常用电子器件学习——MOS管

MOS管介绍 MOS&#xff0c;是MOSFET的缩写。MOSFET 金属-氧化物半导体场效应晶体管&#xff0c;简称金氧半场效晶体管&#xff08;Metal-Oxide-Semiconductor Field-Effect Transistor, MOSFET&#xff09;。 一般是金属(metal)—氧化物(oxide)—半导体(semiconductor)场效应晶…

SpringBoot 中配置处理

1、简介 本文介绍一些 springboot 配置管理相关的内容&#xff0c;如何自定义配置&#xff0c;导入配置&#xff0c;配置绑定和基于 profiles 的配置。 2、springboot 配置管理 2.1、自定义配置类 在 spring 中使用 Configuration 注解定义配置类&#xff0c;在 springboot 中…

利用GPU加速自定义风格图像生成-利用GPU加速结合了ControlNet/ Lora的Stable Diffusion XL

点击链接完成注册&#xff0c;参加本次在线研讨会 https://www.nvidia.cn/webinars/sessions/?session_id240124-31319 随着AI技术的发展, 数字内容创建业务也变得越来越火热。生成式AI模型的发布, 让我们看到了人工智能在各行各业的潜力。您只需要用语言简单描述自己希望看…

【Python】FastApi框架搭建部署

FastApi 是一个现代、快速&#xff08;高性能&#xff09;的 web 框架&#xff0c;用于基于标准Python构建的API。 官方网址&#xff1a;FastAPI 1.安装 1.1 环境信息 # Python版本 3.8.0 1.2 安装 FastApi pip install fastapi # uvicorn 作为服务启动fastapi框架 pip i…

【牛客】几何糕手、国际裁判带师、数位dp?、灵异背包、矩阵快速幂签到、第一次放学

文章目录 《几何糕手》题目描述思路代码 《国际裁判带师》题目描述思路代码 《数位dp?》题目描述思路代码 《灵异背包》题目描述思路代码 《矩阵快速幂签到》题目描述思路代码 《第一次放学》题目描述思路代码 《几何糕手》 题目链接 题目描述 “芝士肾么&#xff1f;” 地…

Mysql的骚操作说明

Mysql的常规操作 记录些不常用,但是很实用的操作,旨在在MySQL语言能解决的批量操作的问题,不动用其他动态或静态语言的辅助。 1、FROM_UNIXTIME 时间戳转时间格式 select scode,sid,gender,type,FROM_UNIXTIME(report_time) as report_time,FROM_UNIXTIME(add_time) as add…

基于SpringBoot的教务管理系统设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于SpringBoot的教务管…

finalshell连接linux的kali系统

kali的ssh服务似乎是默认关闭的&#xff0c;笔者在玩CentOS系统时可以直接用finalshell完成连接&#xff0c;但kali不行&#xff0c;需要先手动开启ssh服务。 开启kali的ssh服务 输入【ssh start】命令开启ssh服务&#xff0c;可以用【ssh status】命令查看ssh状态&#xff0c…

【Linux】vim 操作指令详解

Linux 1 what is vim &#xff1f;2 vim基本概念3 vim的基本操作 &#xff01;3.1 vim的快捷方式3.1.1 复制与粘贴3.1.2 撤销与剪切3.1.3 字符操作 3.2 vim的光标操作3.3 vim的文件操作 总结Thanks♪(&#xff65;ω&#xff65;)&#xff89;感谢阅读下一篇文章见&#xff01;…

API协议设计的十种技术

文章目录 前言一、REST二、GraphQL三、gRPC&#xff08;google Remote Procedure Calls&#xff09;四、Webhooks五、服务端的事件发送——SSE&#xff08;Server-sent Events&#xff09;六、EDI&#xff08;Electronic Data Interchange&#xff09;七、面向API 的事件驱动设…

【.NET Core】深入理解异步编程模型(APM)

【.NET Core】深入理解异步编程模型&#xff08;APM&#xff09; 文章目录 【.NET Core】深入理解异步编程模型&#xff08;APM&#xff09;一、APM概述二、IAsyncResult接口2.1 BeginInvoke2.2 EndInvoke2.3 IAsyncResult属性2.4 IAsyncResult异步演示 三、通过结束异步操作来…

【Linux】yum本地配置

配置将来是在干什么&#xff1f; yum会根据/etc/yum.repos.d/该路径下面的配置文件&#xff0c;来构成自己的下载路径&#xff0c;&#xff08;根据OS版本&#xff0c;根据你要下载的软件&#xff09;&#xff0c;yum帮助我们下载&#xff0c;安装 一般的机器&#xff0c;内置…

Operation

contents 服务器一、相关概念1.1 云服务器与实例1.2 关于域名解析延时与80端口1.3 关于备案1.4 关于SSL证书1.5 关于SSL证书的签发1.6 关于SSL证书的部署1.7 关于LNMP和LAMP1.8 关于bt面板 二、单服务器单一级域名多网站2.1 创建多个二级域名2.2 解析二级域名绑定到服务器上2.3…

【QML COOK】- 011-动画插值设置

QML中内置了一些动画插值类型。不同的插值类型可以通过Animation的easing属性设置。具体可见&#xff1a;PropertyAnimation QML Type | Qt Quick 6.6.1 1. 创建工程在Main.qml&#xff0c;中编写如下代码 import QtQuickWindow {width: 1000height: 100visible: truetitle: …

数字人直播系统跟无人直播系统的区别是什么?如何选择呢?

有媒体预测&#xff0c;未来几年&#xff0c;数字人工智能将呈现爆发式的增长&#xff0c;数字人系统将广泛应用于各个行业&#xff0c;比如数字人直播&#xff0c;数字人短视频播报&#xff0c;数字人制作的海报宣传等等&#xff0c;当然&#xff0c;这其中应用最广的当属数字…

Python实现离散选择Logit模型(Logit算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 Logit模型&#xff08;Logit model&#xff0c;也译作“评定模型”&#xff0c;“分类评定模型”&…

从想象到现实:Midjourney的AI图像生成之旅

从想象到现实&#xff1a;Midjourney的AI图像生成之旅 继ChatGPT之后&#xff0c;Midjourney作为AI艺术的璀璨明珠&#xff0c;吸引了全球范围内的广泛关注。这款工具通过先进的AI技术&#xff0c;将用户输入的文字描述转化为精美绝伦的图像。无论是风景画、肖像画还是抽象艺术…

CentOS7的安装配置

一. CentOS7的安装【在虚拟机中】 首先创建一个虚拟机&#xff0c; 这个没什么好说的&#xff0c;基本上都是下一下一步安装。 注意它的存放位置最好不要放在C盘&#xff0c; 以及开始创建时选择”稍后安装操作系统“ 创建完成后再配置镜像文件 开启虚拟机&#xff0c;继续下…