Spring IOC 控制反转(注解版)

Spring IOC 控制反转

文章目录

  • Spring IOC 控制反转
    • 一、前言
      • 什么是控制反转(IOC)
      • 什么是依赖注入(DI)
    • 二、介绍 IOC
      • 2.1 传统思想代码
      • 2.2 解决方案
      • 2.3 IOC思想代码
      • 2.4 IOC 使用(@Autowired依赖注入)
      • 2.5 IOC 优势
    • 三、IOC详解
      • 3.1 从Spring容器中获取对象:Spring上下文
      • 3.2 Bean的存储
        • 3.2.1 为什么要这么多类注解?
      • 3.3 方法注解@Bean
        • 3.3.1 @Bean方法注解一定要配合类注解使用
        • 3.3.2 @Bean方法定义多个对象
        • 3.3.3 重命名@Bean
      • 3.4 扫描路径
    • 四、三种依赖注入方式(DI)
      • 4.1 属性注入
        • 4.1.1 @Autowired存在问题
      • 4.2 构造方法注入
      • 4.3 Setter注入
    • 五、常见面试题
      • 5.1 常见面试题:@Autowired与@Resource的区别
      • 5.2 常见面试题:三种注入方式的优缺点
    • 六、附加总结

一、前言

Spring 框架中的核心概念之一就是控制反转(Inversion of Control,IoC)

IOC就是一种思想,而依赖注入(Dependency Injection, DI) 是控制反转的一种实现方式。

Spring本身是一个容器,存的是对象。对象这个词,在 Spring的范围内,称之为 Bean。

什么是控制反转(IOC)

控制反转(Inversion of Control,IoC)是一种设计原则,它将对象的创建和依赖关系的管理从程序代码中解耦出来,交由框架或容器进行处理。传统的编程方式中,应用程序代码主动创建和管理对象,而通过IoC,框架或容器负责对象的创建和管理,应用程序代码只需要声明依赖关系。转换对象控制权,让Spring帮我们管理或创建 bean

什么是依赖注入(DI)

依赖注入(Dependency Injection,DI)是一种设计模式,它将对象所依赖的其他对象的创建和管理职责从对象自身剥离出来,通过外部容器(如Spring IoC容器)将所需的依赖对象注入到目标对象中,从而实现对象之间的解耦和提高代码的可维护性和可测试性。

二、介绍 IOC

下面将通过案例来分析什么是IOC

需求:造一辆车

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.1 传统思想代码

public class NewCarExample {
    public static void main(String[] args) {
        Car car = new Car(20);
        car.run();
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;

        public Car(int size) {
            framework = new Framework(size);
            System.out.println("Car init....");
        }
        public void run(){
            System.out.println("Car run...");
        }
    }

    /**
    *车身类
    */
    static class Framework {
        private Bottom bottom;
        
        public Framework(int size) {
            bottom = new Bottom(size);
            System.out.println("Framework init...");
        }
    }

    /**
     * 底盘类
     */
    static class Bottom {
        private Tire tire;
        
        public Bottom(int size) {
            this.tire = new Tire(size);
            System.out.println("Bottom init...");
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        // 尺寸
        private int size;

        public Tire(int size){
            this.size = size;
            System.out.println("轮胎尺寸:" + size);
        }
    }
}

从上述代码中可以看到,以上程序的问题是代码耦合性过高,导致修改底层代码后,需要调整整体的代码。

2.2 解决方案

利用IOC思想,控制反转。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

具体操作是将原来由我们自己创建的下极类,改为传递的方式(也就是注入的方式)。

因为我们不需要在当前类中创建下极类了,所以下极类及时发生变化,当前类本身也无需修改任何代码,这样就完成了解耦合。

2.3 IOC思想代码

public class IocCarExample {
    public static void main(String[] args) {
        Tire tire = new Tire(20);
        Bottom bottom = new Bottom(tire);
        Framework framework = new Framework(bottom);
        Car car = new Car(framework);
        car.run();
    }

    static class Car {
        private Framework framework;

        public Car(Framework framework) {
            this.framework = framework;
            System.out.println("Car init....");
        }
        public void run() {
            System.out.println("Car run...");
        }
    }

    static class Framework {
        private Bottom bottom;

        public Framework(Bottom bottom) {
            this.bottom = bottom;
            System.out.println("Framework init...");
        }
    }

    static class Bottom {
        private Tire tire;

        public Bottom(Tire tire) {
            this.tire = tire;
            System.out.println("Bottom init...");
        }
    }

    static class Tire {
        private int size;

        public Tire(int size) {
            this.size = size;
            System.out.println("轮胎尺寸:" + size);
        }
    }
}

2.4 IOC 使用(@Autowired依赖注入)

Spring 作为一个IOC容器帮我们管理对象,其主要功能就是

存:存的是对象bean,可以使用 @Component或者其他注解(下文中会讲到)

取:告诉 Spring ,从容器中取出这个对象,赋值给当前对象的属性。也就是依赖注入 使用注解 @Autowired

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.5 IOC 优势

传统开发中,对象创建的顺序是:Car -> Framework -> Bottom -> Tire

改进之后解耦代码的创建顺序是:Tire -> Bottom -> Framework -> Car

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们发现了一个规律,通用程序的实现代码,类的创建顺序是反的,传统代码是 Car 控制并创建了Framework,Framework 创建并创建了 Bottom,依次往下,而改进之后的控制权发生的反转,不再是使用方对象创建并控制依赖对象了 ,而是把依赖对象注入将当前对象中,依赖对象的控制权不再由当前类控制了。

这样的话,即使依赖类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。

上述改进后的程序main中的代码就是IOC容器需要存储的数据。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上面也可以看出来, IoC容器具备以下优点:

资源不由使用资源的双方管理,而由不使用资源的第三方管理。

  • 资源的集中管理:IOC会帮我们管理一些资源(对象等),需要的时候,直接去IOC中取即可。
  • 在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,降低耦合度。

三、IOC详解

前面提到的IOC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对象。也就是存储bean。

3.1 从Spring容器中获取对象:Spring上下文

在学习如何存储对象之前,先来看如何从Spring容器中获取对象?

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		//String上下文
		ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        //获取到这个类的对象
        context.getBean(Class<T> aClass);
        //根据bean名称获取bean
        context.getBean(String s);
    }
}

获取Bean的三种常用方法外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过Bean名称来获取Bean,如果没有显式的提供名称(BeanId),Spring容器将为该bean生成唯一的名称。

Bean的命名约定:查看官方文档

其大致意思是,bean名称以小写字母开头,然后使用驼峰式大小写

比如:

类名:UserController,Bean的名称为:userController;

类名:AccountManager,Bean的名称为:accountManage;

也有特殊情况:

比如 :

类名:UController,Bean的名称为:UController;

类名:AController,Bean的名称为:AController;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
        //上下文
		ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        //通过类名获取bean
        UserController usercontroller1 = context.getBean(UserContorller.class);
        //通过Bean名获取bean
        UserController usercontroller2 = context.getBean(userController);
        
        system.out.println(usercontroller1);
        system.out.println(usercontroller2);
    }
}

3.2 Bean的存储

在Spring中,要把某个对象交给IOC容器管理,需要在类上添加注解,下文中就会讲到Spring框架为服务web应用程序,提供了丰富的注解。

共有两类注解类型可以实现:

  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. 方法注解:@Bean

观察下面类注解的源代码,都是@component的衍生类,因此@Component的作用范围更广。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

@Controller控制存储器

@Service服务存储

@Repository仓库存储

@Component组件存储

@Configuration配置存储

3.2.1 为什么要这么多类注解?

最直接的一个原因就是,可以让程序员看到类注解之后,就能直接了解当前类的用途。

  • @Controller:控制层, 接收请求, 对请求进行处理, 并进行响应.
  • @Servie:业务逻辑层, 处理具体的业务逻辑.
  • @Repository:数据访问层,也称为持久层. 负责数据访问操作
  • @Configuration:配置层. 处理项目中的一些配置信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.3 方法注解@Bean

五大注解只能加在类上,并且只能加在自己的代码上,如果我引入了一个第三方jar包,也希望交给Spring管理,是没有办法加五大注解。比如说:数据库操作,定义多个数据源

@Bean方法一定要配合类注解使用

使用@Bean注解时,bean的名称是方法名。

3.3.1 @Bean方法注解一定要配合类注解使用

在 Spring 框架的设计中,方法注解 要配合类注解才能将对象正常的存储到 Spring 容器中,下代码所示:

@Component
public class BeanConfig {
    @Bean
    public User user(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}
3.3.2 @Bean方法定义多个对象

对于同一个类,如何定义多个对象呢?

比如说,多数据源的场景,类是同一个,但是配置不同,指向的数据源也不同。

@Component
public class BeanConfig {
    @Bean
    public User user1(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User user2(){
        User user = new User();
        user.setName("lisi");
        user.setAge(19);
        return user;
    }
}

此时,如果通过类型获取对象的话,Spring就会给我们报错,因为有两个对象,Spring不知道取哪个。接下来根据名称来获取bean对象。

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        //根据bean名称, 从Spring上下文中获取对象
        // User user1 = (User) context.getBean("user1");
        User user2 = (User) context.getBean("user2");
        System.out.println(user1);
        System.out.println(user2);
    }
}
3.3.3 重命名@Bean
@Bean(name = {"u1","user1"})
public User user1(){
    User user = new User();
    user.setName("zhangsan");
    user.setAge(18);
    return user;
}

3.4 扫描路径

SpringBoot 特点就是约定大于配置。其中之一的体现就是扫描路径。

默认扫描路径:启动类所在的目录及其子孙目录

如果更改启动类所在目录,而未进行路径的标注就会出现报错。

通过@ComponentScan()这个注解可以指定扫描路径。

@ComponentScan({"com.example.demo"})
@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		//获取Spring上下文对象
		ApplicationContext context = SpringApplication.run(DemoApplication.class, args);
				//从Spring上下文中获取对象
		User u1 = (User) context.getBean("u1");
		//使用对象
		System.out.println(u1);
	}
}

四、三种依赖注入方式(DI)

上面我们讲解了控制反转IoC的细节,接下来呢,我们学习依赖注入DI的细节。依赖注入是一个过程,是指IoC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象。在上面程序案例中,我们使用了@Autowired这个注解,完成了依赖注入的操作。

关于依赖注入,Spring也给我们提供了三种方式:

  • 属性注入
  • 构造方法注入
  • Setter注入

4.1 属性注入

属性注入是使用@Autowired实现的。

下面是将Service类注入到Controller类中。

//Service类
import org.springframework.stereotype.Service;
@Service
public class UserService {
    public void sayHi() {
        System.out.println("Hi,UserService");
    }
}
@Controller
public class UserController {
    //注入方法1: 属性注入
    @Autowired
    private UserService userService;

    public void sayHi(){
        System.out.println("hi,UserController...");
        userService.sayHi();
    }
}
4.1.1 @Autowired存在问题

当一个类存在多个bean时,使用@Autowored会存在问题

@Component
public class BeanConfig {

    @Bean()
    public User user1() {
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setName("lisi");
        user.setAge(19);
        return user;
    }
}
@Controller
public class UserController {

        @Autowired
        private UserService11 userService;
    
        //此时注入的user,Spring不知道是user1还是user2
        @Autowired
        private User user;

        public void sayHi() {
                System.out.println("hi,UserController...");
                userService.sayHi();
                System.out.println(user);
        }
}

运行程序就会报错外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

报错原因是非唯一的Bean对象。

Spring提供了以下几种解决方案:

  • Primary
  • Qualifier
  • Resource

使用@Primary注解: 当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现.

@Component
public class BeanConfig {

    //此时Spring默认的就是user1()
    @Primary
    @Bean()
    public User user1() {
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setName("lisi");
        user.setAge(19);
        return user;
    }
}

使用@Qualifier注解:指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。

@Controller
public class UserController 
    
    @Autowired
    private UserService11 userService;

    @Qualifier("user2") //指定bean名称
    @Autowired
    private User user;

    public void sayHi() {
            System.out.println("hi,UserController...");
            userService.sayHi();
            System.out.println(user);
    }
}

使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。

@Controller
public class UserController 
    
    @Autowired
    private UserService11 userService;

    @Resource(name = "user2")
    private User user;

    public void sayHi() {
            System.out.println("hi,UserController...");
            userService.sayHi();
            System.out.println(user);
    }
}

4.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,代码如下:

@Controller
public class UserController2 {
    //注入方法2: 构造方法
    private UserService userService;

    @Autowired
    public UserController2(UserService userService) {
        this.userService = userService;
    }

    public void sayHi(){
        System.out.println("hi,UserController2...");
        userService.sayHi();
    }
}

4.3 Setter注入

Setter注入和属性的Setter方法实现类似,只不过在设置 set 方法的时候需要加上@Autowired注解,代码如下:

@Controller
public class UserController3 {
    //注入方法3: Setter方法注入
    private UserService us;

    @Autowired
    public void setUS(UserService us) {
        this.us = us;
    }

    public void sayHi(){
        System.out.println("hi,UserController3...");
        userService.sayHi();
    }
}

五、常见面试题

5.1 常见面试题:@Autowired与@Resource的区别

  • @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解

  • @Autowired 默认是按照类型注入,而@Resource是按照名称注入. 相比于@Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。

5.2 常见面试题:三种注入方式的优缺点

  • 属性注入(大部分情况下使用)
    • 优点:简洁、使用方便。
    • 缺点:
      • 不能注入一个Final修饰的属性。
      • 只能用于IOC容器,如果是非IOC容器则不可用。并且在使用的时候才会出现 NPE(空指针异常)
  • 构造函数注入(Spring 4.x推荐)
    • 优点:
      • 可以注入Final修饰的属性。
      • 注入的对象不会被修改。
      • 通用性比较好,构造方法是JDK支持的,因此更换框架也是适用的。
    • 缺点:注入多个对象时,代码比较复杂。
  • Setter注入(Spring 3.x推荐)
    • 优点:方便在类实例之后,重新对该对象进行配置或注入。
    • 缺点:
      • 不能注入一个Final修饰的对象。
      • 注入对象有被修改的风险。

六、附加总结

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

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

相关文章

Service方法增加@Asyn注解后导致bean无法找到 NoSuchBeanDefinitionException

Service方法增加Asyn注解后导致bean无法找到 NoSuchBeanDefinitionException 场景处理方法原因 场景 首先确认的是Service添加了Service或Component等注解&#xff0c;另外也增加了ComponentScan确定扫描的包路径是包含对应Service的&#xff0c;但就是无法找到这个bean。 通…

从艳彩山水到艳彩艺术 薛永年:郭泰来艳彩艺术填补了中国美术史的空白

薛永年先生 自6月12日开展以来&#xff0c;郭泰来现代艺术大展杭州如火如荼地进行着&#xff0c;吸引了众多艺术爱好者和专业人士前往。毫不夸张地说&#xff0c;总统和清洁工人都能在他的作品中找到自己心中的那一块共振带并与之产生强烈的共鸣&#xff0c;这便是郭泰来先生的…

Vector 例题

例题一&#xff1a; 下面这个代码输出的是( ) &#xfeff;#include <iostream> #include <vector> using namespace std; int main(void) { vector<int>array; array.push_back(100); array.push_back(300); array.push_back(300); array.push_back(300); a…

Python学习笔记16:进阶篇(五)异常处理

异常 在编程中&#xff0c;异常是指程序运行过程中发生的意外事件&#xff0c;这些事件通常中断了正常的指令流程。它们可能是由于错误的输入数据、资源不足、非法操作或其他未预料到的情况引起的。Python中&#xff0c;当遇到这类情况时&#xff0c;会抛出一个异常对象&#…

34.构建核心注入代码

上一个内容&#xff1a;33.获取入口点 以 33.获取入口点 它的代码为基础进行修改 实现的功能是把LoadLibrary函数注入到目标进程实现加载我们的模块。LoadLibrary只有有程序使用过了它的代码就会加载到内存中&#xff08;因为动态链接库是内存加载&#xff09;就是a程序要用L…

QThread 与QObject::moveToThread在UI中的应用

1. QThread的两种用法 第一种用法就是继承QThread&#xff0c;然后覆写 virtual void run()&#xff0c; 这种用法的缺点是不能利用信号槽机制。 第二种用法就是创建一个线程&#xff0c;创建一个对象&#xff0c;再将对象moveToThread, 这种可以充分利用信号槽机制&#xff…

Polyp-DDPM: Diffusion-Based Semantic Polyp Synthesis for Enhanced Segmentation

Polyp- ddpm:基于扩散的语义Polyp合成增强分割 摘要&#xff1a; 本研究介绍了一种基于扩散的方法Polyp-DDPM&#xff0c;该方法用于生成假面条件下息肉的逼真图像&#xff0c;旨在增强胃肠道息肉的分割。我们的方法解决了与医学图像相关的数据限制、高注释成本和隐私问题的挑…

尚硅谷大数据技术ClickHouse教程-笔记01【ClickHouse单机安装、数据类型】

视频地址&#xff1a;一套上手ClickHouse-OLAP分析引擎&#xff0c;囊括Prometheus与Grafana_哔哩哔哩_bilibili 01_尚硅谷大数据技术之ClickHouse入门V1.0 尚硅谷大数据技术ClickHouse教程-笔记01【ClickHouse单机安装、数据类型】尚硅谷大数据技术ClickHouse教程-笔记02【表引…

Comfy UI使用最新SD3模型,并解决报错‘NoneType‘ object has no attribute ‘tokenize‘【实测可行】

解决Comfy UI使用最新SD3模型报错’NoneType’ object has no attribute ‘tokenize’ 前几天SD3发布了&#xff0c;所以想着尝尝鲜&#xff0c;便去下载了SD3来玩一玩。使用的是Comfy UI而不是Stable Diffusion UI&#xff0c;这是一个比SD UI更加灵活的UI界面&#xff0c;使用…

内容安全复习 4 - 深度生成模型

文章目录 概述经典算法自回归模型&#xff08;Autoregressive model&#xff09;变分自编码器&#xff08;VAE&#xff09;生成对抗网络&#xff08;GAN&#xff09;扩散模型&#xff08;Diffusion model&#xff09;总结 应用 概述 深度生成模型是一类使用深度学习技术构建的…

L55--- 257.二叉树的所有路径(深搜)---Java版

1.题目描述 2.思路 &#xff08;1&#xff09;因为是求二叉树的所有路径 &#xff08;2&#xff09;然后是带固定格式的 所以我们要把每个节点的整数数值换成字符串数值 &#xff08;3&#xff09;首先先考虑根节点&#xff0c;也就是要满足节点不为空 返回递归的形式dfs(根节…

数字内容“遍地开花”,AI技术如何创新“造梦”?

文 | 智能相对论 作者 | 陈泊丞 这是春晚舞台西安分会场《山河诗长安》的一幕&#xff1a;“李白”现世&#xff0c;带领观众齐颂《将进酒》&#xff0c;将中国人骨子里的豪情与浪漫演绎得淋漓尽致。 这又是浙江义乌商品市场里的另一幕&#xff1a;只会说几个英文单词的女老板…

入门Ansible常用模块

自动化运维Devops-Ansible Ansible是新出现的自动化运维工具&#xff0c;基于Python 开发&#xff0c;集合了众多运维工具&#xff08;puppet 、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置 、批量程序部署、批量运行命令 等功能。Ansible…

小程序 如何支付后获取 Unionid

接口说明 接口英文名 getPaidUnionid 功能描述 该接口用于在用户支付完成后&#xff0c;获调用本接口前需要用户完成支付&#xff0c;用户支付完成后&#xff0c;取该用户的 UnionId&#xff0c;无需用户授权。本接口支付后的五分钟内有效。 注意事项 调用前需要用户完成…

直播websocket签名signature字段生成逻辑,一步一步带你研究学习

现在每个直播的链接都要签名字段才可以校验成功&#xff0c;所以需要开始debug逻辑&#xff0c;研究一下这个加密的签名字段哪里来的&#xff0c;先找到这个发送请求的js代码在哪里&#xff1a; 找到发送websocket的地方了&#xff0c;看了一下_getSocketParams这就是获取请求参…

String(C++)

文章目录 前言文档介绍经典题目讲解HJ1 字符串最后一个单词的长度 模拟实现框架构造函数析构函数迭代器c_str()赋值size()capacity()reserveempty()[ ]访问front/backpush_backappendoperatorinsert一个字符insert一个字符串eraseswapfind一个字符find一个字符串substr()clear(…

超级会员卡积分收银系统源码 带完整的安装代码包以及搭建部署教程

系统概述 超级会员卡积分收银系统源码是一款专为商业运营打造的综合性软件解决方案。它集成了会员卡管理、积分管理、收银管理等多种功能&#xff0c;旨在为企业提供高效、便捷、准确的运营管理工具。 该系统源码采用先进的技术架构&#xff0c;具有良好的稳定性和扩展性&…

Python火焰锋动力学和浅水表面波浪偏微分方程

&#x1f3af;要点 &#x1f3af;流图可视化正弦余弦矢量场 | &#x1f3af;解空间变化边界条件二维拉普拉斯方程 | &#x1f3af;解圆柱坐标系标量场 | &#x1f3af;解一维泊松方程 | &#x1f3af;解二维扩散方程 | &#x1f3af;解火焰锋的动力学偏微分方程 | &#x1f3a…

自动备份SQL Server数据库,试试这4种方法!

各种规模的企业都使用 SQL 数据库来存储数据。因此&#xff0c;备份 SQL Server 数据库对于确保数据安全并在发生灾难时可恢复至关重要。对于 SQL 数据库备份&#xff0c;有多种可行的方法&#xff0c;对于特定组织来说&#xff0c;方法将取决于其具体需求。 SQL Server 备份的…

Vue69-路由基本使用

一、需求 二、开发步骤 2-1、路由的安装 vue-router3才能在vue2中使用&#xff01;现在默认是vue-router4版本&#xff0c;要在vue3中使用&#xff01;所以&#xff0c;安装的时候要指定版本。 2-2、在main.js中引入和使用路由 2-3、创建router文件夹 一般在vue中用了vue-ro…