《JavaEE进阶》----11.<SpringIOCDI【Spring容器+IOC详解+DI介绍】>

news2024/11/13 9:33:12

本篇博客会详细讲解什么是Spring。

SpringIOC

SpringID

五个类注解:@Controller、@Service、@Repository、@Component、@Configuration

一个方法注解:@Bean

什么是Spring

IOC容器

Spring 是包含众多工具的IOC容器。能装东西的容器。

1.容器

如我们之前学的

TomCat就是Web容器

list/map:数据容器

学校:学生的容器。

Spring容器:是一个装对象的容器

2.IOC(Inversion of Control):控制翻转(控制权翻转)。指的是对象的控制权,对象交给Spring控制。指的是获取依赖对象的权利/过程。

IOC在之前的博客SpringMVC项目实践中已经用到了。就是我们在类上面添加注解。

@RestController和@Controller注解。

就是把这个对象交给Spring管理。Spring框架启动时就会加载该类。把对象交给Spring管理,就是IoC思想.

传统开发中:

对象谁使用谁控制

当我们想要获取依赖对象。我们需要new一个对象。这个对象定义在方法中 或者 定义在外面。这个对象的控制权都是谁使用谁控制。

现代开发中

对象交给Spring控制

现在我们已经不需要自己去创建这个对象。而是把创建对象的任务交给Spring容器(也就是Spring、SpringIOC容器)。我们只需要在程序中通过依赖注入(DI)(Dependeny Injection)就可以了。

控制反转思想在生活中的体现。

如开车。(驾驶权控制反转)

传统驾驶方式驾驶控制权是驾驶员的。

现在自动驾驶,驾驶权交给了自动驾驶系统。

如招聘,

企业的员工招聘,入职。解雇等控制权,从老板控制。

现在转交给HR(human resources)(人力资源)来处理

经典面试题:

1.Spring,SpringBoot,SpringMVC之间的区别和联系,你是如何理解的?

我的理解

1.Spring 是一个框架

2.SpringBoot 使我们在创建项目的时候可以直接添加一些依赖。并且内置web服务器、提供许多注解方便我们书写代码。对项目进行更多的监控指标,更好的了解项目的运行情况。简化我们的开发。

3.SpringMVC 是一个框架。是针对Web开发的一种MVC的思想的实现。也被称作Spring Web MVC(Spring Web)。在创建项目时,我们添加的依赖Spring Web实际上引的就是SpringMVC。可以认为Spring给我们提供的Web功能就叫做SpringMVC。

假如把Spring看作火车。(而做项目相当于坐火车) 但是它买票不方便。 

因此就可以把SpringBoot看作是12306。而12306不仅可以订票还可以订酒店。打的等等。让我们坐火车(做项目更加的方便)

而SpringMVC 可以认为是火车里面提供的一些功能。比如买票,改签,插座等等。(注解/Cookie&Session)

2.Spring两大核心思想IOC和AOP

待续

3.常见面试题:ApplicationContext VS BeanFactory

1.继承关系和功能方面来说:

Spring 容器有两个顶级的接口:BeanFactory和 ApplicationContext。其中BeanFactory提供了基础的访问容器的能力,而ApplicationContext 属于BeanFactory的⼦类,它除了继承了BeanFactory的所有功能之外, 它还拥有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持.

2.从性能方面来说:

ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象,而BeanFactory 是需要那个才去加载那个,因此更加轻量. (空间换时间) 

一、IOC介绍+代码实践

通过一些代码,更清楚的理解Spring中的IOC。

通用程序的实现代码,类的创建顺序是反的。

总结:

传统代码

是Car控制并创建了Framework。Framework创建并创建了Bottom,依次往下

IOC思想

是把依赖对象注⼊将当前对象中,依赖对象的控制权不再由当前类控制了.这样的话,即使依赖类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。

这部分代码就是IOC容器做的工作。

IOC容器的优点

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

1.资源集中管理:IOC容器会帮我们管理一些资源(对象等)。我们使用时,从IOC容器取就可以了。

2.在创建实例的时候不需要了解其中的细节。降低了使用资源双方的依赖程度。也就是耦合度。

Spring就是一种IOC容器。帮助我们来做了这些资源。

1.1传统方式代码造车 

public class TraditionNewCarExample {
    /**
     * 传统方式造车
     * 1.先造轮胎
     * 2.再造底盘
     * 3.再造车身
     * 4.汽车出品
     * 这样设计可维护性很低。比如当需要加工多种尺寸的轮胎。
     * 这时候就需要对程序进行修改。我们会发现牵一发而动全身。
     * 我们需要去传入参数了。
     *
     * 创建对象的方式是:new car -> new Framework -> new bottom -> new tire
     */


    static class Tire{
        private int size;

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

    static class Bottom{
        private Tire tire;

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

    static class Framework{

        private Bottom bottom;

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

    static class Car{
        private Framework framework;

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

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


    public static void main(String[] args) {

        Car car = new Car();
        car.run();
    }
}

1.2 更新维护传统方式的代码

public class RenewTraditionNewCar {

        /**
         * 传统方式造车
         * 1.先造轮胎
         * 2.再造底盘
         * 3.再造车身
         * 4.汽车出品
         * 这样设计可维护性很低。比如当需要加工多种尺寸的轮胎。
         * 这时候就需要对程序进行修改。我们会发现牵一发而动全身。
         * 我们需要去传入参数了。
         * 下面是对传统新建汽车的修改
         * 可以看出,当最底层的代码改动之后。整个调用链上的所有代码都需要修改。
         * 因此代码耦合度非常高。
         */


        static class Tire{
            private int size;

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

        static class Bottom{
            private Tire tire;

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

        static class Framework{

            private Bottom bottom;

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

        static class Car{
            private Framework framework;

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

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


        public static void main(String[] args) {

            Car car = new Car(15);
            car.run();
        }
}

1.3IOC思想代码造车

/**
 * IOC模式造车
 * 把创建子类的方式改为注入传递的方式。
 *
 * 创建对象的方式是:new tire -> new bottom -> new Framework -> new tire
 */
public class IOCNewCar {
    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 Tire{
        private int size;

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

    static class Bottom{
        private Tire tire;

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

    static class Framework{
        private Bottom bottom;

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

    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...");
        }
    }

}

 二、DI介绍

什么是DI呢?

Dependency Injection(依赖注入)

容器在运行期间,动态的为应用程序提供运行时所依赖的资源。称为依赖注入

依赖注入(DI)和控制翻转(IOC)是从不同的角度描述同一件事。

就是指通过引入IOC容器。利用依赖关系注入的方式。实现对象之间的解耦合。

IoC是一种思想。 

IoC是对象的控制反转,主要是用来创建对象的。实现把创建的对象的控制权交给Spring容器。

IOC是对依赖对象的创建。依赖对象的控制权交给Spring。管理依赖对象,对应存。

DI就是具体的实现。也就是DI是IoC的一种实现。

依赖注入,对IoC创建的依赖进行对象注入。可以认为依赖注入是如何拿到和使用IoC创建的依赖对象。对应取。

就像MVC是一种思想,而SpringMVC是具体的实现。

上面IOC思想代码造车的案例就是通过构造函数的方式,把依赖对象注入到需要使用的对象中

三、Spring IoC 和 DI的基本操作

 上面是初步了解。接下来具体学习SpringIoC和DI的代码实现。我们还会用到许多的注解。

Spring是IOC容器。那么容器就有最基础的两个功能:

  • 存对象(@Component)加上这个注解相当于我们把这个对象交给Spring管理了
  • 取对象(@AutoWired)加上这个注销相当于我们把这个对象从Spring拿出来了

 Spring容器 管理的主要是对象,这些对象我们称之为  “Bean”。我们把这些对象交给Spring管理。

由Spring负责对象的创建和销毁。

我们写的程序只需要告诉Spring哪些需要存。以及如何从Spring中取出对象。

我们下面以写图书管理系统为例。将Controller层、Service层、Dao层的解耦。

3.1把BookDao 交给Spring管理,由Spring来管理对象

Dao层

@Component
public class BookDao {
    /**
     * 1.把BookDao交给Spring管理,由Spring来管理对象。
     * 数据Mock 获取图书信息
     */
    public List<BookInfo> mockData() {
        List<BookInfo> books = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            BookInfo book = new BookInfo();
            book.setId(i);
            book.setBookName("书籍"+i);
            book.setAuthor("作者"+i);
            book.setCount(i*5+3);
            book.setPrice(new BigDecimal(new Random().nextInt(100)));
            /**
             * new Random().nextInt(100):
             * 这一部分代码使用java.util.Random类生成一个随机整数。
             * nextInt(100)会生成一个范围在0(含)到100(不含)之间的随机整数。
             */
            book.setPublish("出版社"+i);
            book.setStatus(1);
            books.add(book);
        }
        return books;
    }
}

3.2把BookService交给Spring管理,由Spring来管理对象

Service层

@Component
public class BookService {

    private BookDao bookDao = new BookDao();

    public List<BookInfo> getBookList(){
        List<BookInfo> books = bookDao.mockData();

        for (BookInfo book:books){
            if(book.getStatus() == 1){
                book.setStateCN("可借阅");
            }else {
                book.setStateCN("不可借阅");
            }
        }
        return books;
    }
}

3.3把BookController交给Spring管理,由Spring来管理对象

@RestController
@RequestMapping("/book")
public class BookController {

    @Autowired
    private BookService bookService;

    @RequestMapping("/getList")
    public List<BookInfo> getList(){
        List<BookInfo> books = bookService.getBookList();
        return books;
    }
}

四、IoC详细用法

五个(类注解)和一个(方法注解)

存对象:

五大类注解@Controller,@Service,@repository,@component,@configuration

一个方法注解@bean. 

@RestController不是,因为@RestController = @ResponseBody+@Controller

它之所以可以帮我们存对象,是里面Controller的原因,而不是其本身。

加了注解Spring会帮我们管理。没有加注解,Spring不会帮我们管理。

4.1 五个类注解

4.1.1五个注解的使用

五个注解属于类注解。他们用法相同。

之所以有五个注解,用法相同是为了分类使用。在存储这块的效果是一样的,

一点点差别

在请求入口上,(有@RequestMapping注解)只能使用@Controller企业规范。

功能上除了Controller都一样。

更多的不同是从概念上赋予了不同的含义。

1.表现层:@Controller

2.业务逻辑层:@Service

3.数据层:Dao,使用的注解是@Repository

除了这些层,还会遇到别的组件如redis等 用@component注解

相关的一些配置 用@configuration注解

分这些注解为了让我们更方便的找到相关代码

在详细介绍五个类注解之前,我们先了解一下启动类。 

@SpringBootApplication启动类

被这个注解标识的叫做启动类

启动类注解。当

ApplicationContext context = SpringApplication.run(IocDomeApplication.class, args);

.run这个方法在运行的时候,就会帮我们创建对象了。创建完对象,有一个返回结果

返回类型为ConfigurableApplicationContext。它的父类是ApplicationContext

ApplicationContext可以认为是spring的一个上下文。可以理解为记录执行内容顺序的存放之处。

可以认为是一个spring的运行环境,spring是一个IOC容器,它的运行环境里面包含了很多个对象,帮我们管理这些对象

这些对象就存放在ApplicationContext。当通过@Controller注解存入了这个对象到Spring容器。我们取的时候,其实具体就是在ApplicationContext中取的。

常用的三种获取bean(对象)的方式。(附带六个注解使用示例)

注意:

1.获取bean的方式用下面的哪个注解都可以。这是只是演示他们是可以存对象到Spring容器的。

2.获取Bean的功能是BeanFeactory提供的。

注:这五个注解的用法是通用的,这里只是讲解获取bean的三种最常用方式。注解无所谓。

bean:Spring管理的对象都称之为bean。

1.根据类型来获取bean(对象)。
①@Controller注解(控制存储)

1.首先使用@Controller注解存储UserController对象

@Controller("bean") //创建对象  //括号中是对bean进行重命名 如果没有指定名称spring帮我们指定
public class UserController {
    public void say(){
        System.out.println("Hi Controller!!!");
    }
}

2.从ApplicationContext取出UserController的对象

3.getBean方法就是获取对象

ApplicationContext context = SpringApplication.run(IocDomeApplication.class, args);
UserController bean1 = context.getBean(UserController.class);
bean1.say();
2.根据名称来获取bean(对象)
②Service注解(服务存储)

1.首先使用@Service注解存储UserService对象

@Service
public class UserService {
    public void say(){
        System.out.println("Hi UserService!!!");
    }
}
bean名称的命名规则

bean这个名称为类名的小驼峰形式。

参考如下打印。l

例外:如果前两位都是大写字母,bean的名称不变,否则是小驼峰形式。

decapitalize("UserService")方法是bean名称的命名规则。

System.out.println(Introspector.decapitalize("UserService"));
//userService

2.从Spring上下文。ApplicationContext类中获取对象

3.可以根据类型来获取对象,但我们换一种根据对象名称(名称被自动从UserService转换为userService)去拿。

而这种方式需要我们根据类型进行强转。这是因为返回类型为Object

ApplicationContext context = SpringApplication.run(IocDomeApplication.class, args);
UserService userService =(UserService) context.getBean("userService");
userService.say();
3.根据名称和类获取bean。
③Component注解

从ApplicationContext获取对象

1.首先使用@Component注解存储UserComponent对象

@Component
public class UserComponent {
    public void say(){
        System.out.println("Hi UserComponent!!!");
    }
}

2.从Spring上下文。ApplicationContext类中获取对象

ApplicationContext context = SpringApplication.run(IocDomeApplication.class, args);

根据名称和类获取bean。

UserComponent userComponent = context.getBean("userComponent", UserComponent.class);
userComponent.say();

④@Repository注解

@Repository
public class UserRepository {
    public void say(){
        System.out.println("Hi Repository!!!");
    }
}

//4.通过Repository注解
UserRepository userRepository = (UserRepository) context.getBean("userRepository");
userRepository.say();

⑤@configuration注解(配置存储)

@Configuration
public class UserConfiguration {
    public void say(){
        System.out.println("Hi Configuration!!!");
    }
}

​//5.通过configuration注解
UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);
userComponent.say();


PS:

Spring是一个服务,服务启动。程序运行完。不会像学语法时那样直接结束。而是会一直提供服务。直到我们结束它。

上下文:

以CPU执行线程为例。CPU一秒执行上亿次。执行速度非常快来实现并发执行。当执行线程1到第二次执行线程1时。CPU怎么知道它执行到哪里了,接着哪里继续执行。这就是通过上下文记录的。Spring的上下文同理。

获取bean对象,父类BeanFactory提供的功能 

4.1.2五大注解之间的关系

我们发现五个类注解中都有@component注解。

我们可以认为,其他是个注解是@component的衍生类。@component也可以称作父类 *

@component是一个元注解。也就是说可以注解其他类注解。

下面三个注解用于更具体的例

@Controller:控制层

@Service:业务逻辑层

@Repository:持久化层

单从功能上看,Controller除了具备让spring管理的功能外,接口的第一层入口必须为Controller,其他怎么调用都行

4.2一个方法注解@Bean

类注解是添加到某个类上的,但是存在两个问题:

1.使用外包部的类,没有办法添加注解

2.一个类,需要多个对象,比如多个数据源。

这种场景我们就需要使用方法注解

 ⑥@Bean注解 的使用

@Bean注解的方法。通过使用@Bean注解,Spring 容器会将这个方法的返回值注册为一个 Bean(对象),从而使其可以被应用程序的其他部分注入和使用。

为了更方便找到@Bean注解,应该告诉Spring哪个类中有@Bean。此时通过@Configuration来根据这个注解生成这个对象

@Bean需要配合五大注解一起使用。

@Bean注解定义的对象,默认名称为方法名

@Bean注解定义的对象,重命名,也是@Bean()在括号中写新名字

4.2.1定义多个对象

定义了多个对象的话,我们根据类型获取对象,获取的是哪个对象呢?

此时会报错哟:期望只有⼀个匹配,结果发现了多个

我们需要

@Bean注解的bean,bean的名称就是它的方法名 

接下来我们根据名称来获取bean对象

@Configuration
public class BeanConfig {
    @Bean
    public UserInfo userInfo(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(120);
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }

    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo2 = new UserInfo();
        userInfo2.setId(121);
        userInfo2.setName("李四");
        userInfo2.setAge(28);
        return userInfo2;
    }
}

取(方法名)

UserInfo userInfo = (UserInfo) context.getBean("userInfo");
UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");
System.out.println(userInfo);
System.out.println(userInfo2);

4.2.2bean的重命名

重命名名字也可以使用数组形式分别命名与之对应的下面的方法。例如:@Bean({"u1","u2"})

bean可以针对同一个类,定义多个对象

@Configuration
public class BeanConfig {
    @Bean({"u1","u2"})
    public UserInfo userInfo(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(120);
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }

    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo2 = new UserInfo();
        userInfo2.setId(121);
        userInfo2.setName("李四");
        userInfo2.setAge(28);
        return userInfo2;
    }
}

取(重命名+类名)

​//6.通过@Bean方法注解
UserInfo userInfo = context.getBean("u1",UserInfo.class);
UserInfo userInfo2 = context.getBean("u2",UserInfo.class);
System.out.println(userInfo);
System.out.println(userInfo2);
​

隐藏条件:

这五大注解必须在Spring的扫描路径下才会生效。

扫描路径默认为:启动类所在的路径。

是被@componentScan标识的当前类所在的路径。@SpringBootApplication包含了@componentScan。因此也是被@SpringBootApplication标识的类

由于本篇博客内容已经很多了,下一篇文章,我们会持续SpringIoC&ID的创作

会详细讲到扫描路径及关于其剩下的知识内容。

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

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

相关文章

高效传输秘籍,揭秘Rsync和SCP的优劣,助你做出明智选择!

在日常的运维工作中&#xff0c;文件传输任务频繁出现&#xff0c;而选择合适的工具能显著提高工作效率。Rsync 和 SCP 是两款常见的文件传输工具&#xff0c;但它们各具优缺点&#xff0c;适合不同的场景。本文将通过深入分析这两款工具的特性、使用场景和性能&#xff0c;帮助…

Django+Vue3前后端分离学习(一)(项目开始时settings.py里的设置)

一、创建django项目 二、修改settings.py里的配置&#xff1a; 1、修改语言和时区&#xff1a; # 语言编码 LANGUAGE_CODE zh-hansTIME_ZONE UTCUSE_I18N True# 不用时区 USE_TZ False 2、配置数据库&#xff1a; DATABASES {default: {ENGINE: django.db.backends.m…

如何启动网络安全计划:首先要做的事情

目录 数据分类&#xff1a;网络安全的基石 为什么它很重要&#xff1f; 如何对数据进行分类&#xff1f; 风险分析 什么是风险分析&#xff1f; 如何进行风险分析&#xff1f; 业务影响分析 (BIA) BIA 的用途是什么&#xff1f; BIA 是如何进行的&#xff1f; 安全解…

文法—语法推导树例题

答案:C 解析&#xff1a; S推出A0&#xff0c;A0推出1&#xff0c;可以推出字符串01 S推出B1&#xff0c;B1推出0&#xff0c;可以推出字符串10 选项A&#xff0c;所有由0构成的字符串&#xff0c;不正确 选项B&#xff0c;所有由1构成的字符串。不正确 选项C&#xff0c…

探索Invoke:Python自动化任务的瑞士军刀

文章目录 探索Invoke&#xff1a;Python自动化任务的瑞士军刀背景&#xff1a;为何选择Invoke&#xff1f;invoke是什么&#xff1f;如何安装invoke&#xff1f;简单的invoke库函数使用方法场景应用&#xff1a;invoke在实际项目中的使用场景一&#xff1a;自动化测试场景二&am…

DAQmx Connect Terminals 路由的实际应用与注意事项

DAQmx Connect Terminals VI 是 NI 数据采集 (DAQ) 系统中的关键功能&#xff0c;用于在物理或虚拟终端之间建立信号路由。它允许用户自定义信号的硬件连接路径&#xff0c;以满足复杂的测试和测量需求。本文将详细介绍如何使用该功能&#xff0c;实际应用中的例子&#xff0c;…

UE5引擎工具链知识点

当我们提到“引擎工具链的开发”时&#xff0c;通常指的是为游戏开发或其他类型的软件开发创建一系列工具和技术栈的过程。这包括但不限于游戏引擎本身&#xff08;如Unity或Unreal Engine&#xff09;&#xff0c;以及围绕这些引擎构建的各种工具和服务&#xff0c;比如用于构…

基于SpringBoot+Vue+MySQL的宿舍维修管理系统

系统展示 前台界面 管理员界面 维修员界面 学生界面 系统背景 在当今高校后勤管理的日益精细化与智能化背景下&#xff0c;宿舍维修管理系统作为提升校园生活品质、优化资源配置的关键环节&#xff0c;其重要性日益凸显。随着学生规模的扩大及住宿条件的不断提升&#xff0c;宿…

Redis 篇-深入了解基于 Redis 实现分布式锁(解决多线程安全问题、锁误删问题和确保锁的原子性问题)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 分布式锁概述 1.1 Redis 分布式锁实现思路 1.2 实现基本的分布式锁 2.0 Redis 分布式锁误删问题 2.1 解决 Redis 分布式锁误删问题 3.0 Redis 分布式锁原子性问题…

高级法医视频分析技术 2024

高级法医视频分析技术 2024 如今&#xff0c;法医视频分析是数字取证的重要组成部分 &#xff0c;因为它可以帮助特工了解视频证据很重要的案件的重要信息。到 2024 年&#xff0c;该领域使用的工具和方法将以前所未有的速度发生变化。在这个领域工作的人需要了解这些变化。在本…

ctfshow-nodejs

什么是nodejs Node.js 是一个基于 Chrome V8 引擎的 Javascript 运行环境。可以说nodejs是一个运行环境&#xff0c;或者说是一个 JS 语言解释器 Nodejs 是基于 Chrome 的 V8 引擎开发的一个 C 程序&#xff0c;目的是提供一个 JS 的运行环境。最早 Nodejs 主要是安装在服务器…

线性代数 第六讲 特征值和特征向量_相似对角化_实对称矩阵_重点题型总结详细解析

文章目录 1.特征值和特征向量1.1 特征值和特征向量的定义1.2 特征值和特征向量的求法1.3 特征值特征向量的主要结论 2.相似2.1 相似的定义2.2 相似的性质2.3 相似的结论 3.相似对角化4.实对称矩阵4.1 实对称矩阵的基本性质4.2 施密特正交化 5.重难点题型总结5.1 判断矩阵能否相…

Flutter集成Firebase中的 A/B Testing

前提 完成Flutter集成Firebase中的远程配置流程 A/B Test的使用流程 我们先通过远程配置设置变量&#xff0c;应用程序根据变量值展示不同的界面创建一个A/B Test实验&#xff0c;在实验中创建满足条件的用户才能加入到这个实验中&#xff0c;并且在A/B 实验中修改远程配置变…

【网络安全】服务基础第二阶段——第二节:Linux系统管理基础----Linux统计,高阶命令

目录 一、Linux高阶命令 1.1 管道符的基本原理 1.2 重定向 1.2.1 输出重定向 1.2.2 输入重定向 1.2.3 wc命令基本用法 1.3 别名 1.3.1 which命令基本语法 1.3.2 alias命令基本语法 1.4 压缩归档tar 1.4.1 第一种&#xff1a;gzip压缩 1.4.2 第二种&#xff1a;bzip…

多款式随身WiFi如何挑选,USB随身WiFi、无线电池随身WiFi、充电宝随身WiFi哪个好?优缺点分析!

市面上的随身WiFi款式多样琳琅满目&#xff0c;最具代表性的就是USB插电款、无线款和充电宝款。今天就来用一篇文章分析一下这三种款式的优缺点。 USB插电款 优点&#xff1a;便宜&#xff0c;无需充电&#xff0c;在有电源的地方可以随时随地插电使用&#xff0c;比如中兴的U…

交换两个变量数值的3种方法

前言&#xff1a;交换两个数值可不是"a b&#xff0c;b a"。这样做的话&#xff0c;a先等于了b的值&#xff1b;当“b a”后&#xff0c;因为此时a已经等于b的值了&#xff0c;这个语句就相当于执行了b b。最终的数值关系就成了a b&#xff0c;b b。 下面教给大…

综合DHCP、ACL、NAT、Telnet和PPPoE进行网络设计练习

描述&#xff1a;企业内网和运营商网络如上图所示。 公网IP段&#xff1a;12.1.1.0/24。 内网IP段&#xff1a;192.168.1.0/24。 公网口PPPOE 拨号采用CHAP认证&#xff0c;用户名:admin 密码:Admin123 财务PC 配置静态IP&#xff1a;192.168.1.8 R1使用模拟器中的AR201型…

重生奇迹MU老大哥剑士职业宝刀未老

重生奇迹MU中&#xff0c;老大哥剑士职业一直以来备受玩家们的喜爱。这个职业不仅拥有强大的攻击力、防御力和战斗技巧&#xff0c;而且还能够通过使用各种宝刀来增强自身的战斗能力。即便经过了多年的沉淀&#xff0c;老大哥剑士依然是一名宝刀未老的男人&#xff0c;仍然能够…

[羊城杯 2021]Ez_android-快坚持不下去的第五天

找到mainactivity函数 1. 用户名和密码的检查 2. 密码的加密然后 - 1 的操作 for (int i 0; i < bArr.length; i) {bArr[i] (byte) (bArr[i] - 1); } 这段代码通过遍历字节数组中的每个元素&#xff0c;将每个元素的值减去 1&#xff0c;并更新数组。这里的 byte 强制转…

怎么给U盘加密来防止数据泄密?总结了五个管用方法

U盘里的数据通常涉及课件、报表、演讲稿等&#xff0c;非常重要&#xff0c;最好能给U盘加密&#xff0c;这样即使丢了也无法看到里面的内容&#xff0c;那么如何给U盘加密呢&#xff1f; 一、使用Windows BitLocker To Go&#xff08;仅限Windows用户&#xff09; 操作步骤&a…