【Spring】之Ioc和Aop快速了解

news2024/12/23 0:43:10

这里写目录标题

  • 1.Spring框架是什么?
        • 简介:
          • 总结:Spring框架,可以理解为是一个管理者:管理整个分层架构(MVC)中的每一个对象;(每一个对象称之为bean)
  • 2.Spring框架的优缺点
    • 2.1优点
    • 2.2缺点
  • 3.框架学习什么?
  • 4.Spring框架做什么?
          • 目的:管理对象
          • IOC控制反转:(Inversion Of Control),即就是:将对象的控制权从自己new改为跟Spring要;
  • 5.Spring之IoC
    • 5.1核心概念
    • 5.2 IoC的技术实现
    • 5.3 完成IoC的步骤
    • 5.4 Spring容器对象的方法
    • 5.5 IoC的依赖注入:DI
    • 5.6 基于注解的di(重点)
      • 5.6.1 @Component注解
      • 5.6.2 @Respotory、@Service、@Controller 注解
      • 5.6.3 @Value
      • 5.6.4 @Autowired
      • 5.6.5 @Resource

1.Spring框架是什么?

简介:

Spring就像是整个项目中装配bean(对象)的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。也可以称之为项目中的粘合剂。Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地new一个对象,而是让Spring框架帮你来完成这一切。(包括:对象的创建、对象之间的关系)

总结:Spring框架,可以理解为是一个管理者:管理整个分层架构(MVC)中的每一个对象;(每一个对象称之为bean)

2.Spring框架的优缺点

2.1优点

  • 轻量:Spring 框架运行占用的资源少,运行效率高。不依赖其他 jar
  • 针对接口编程,解耦合:Spring 提供了 Ioc 控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成。对象之间的依赖解耦合。
  • AOP 编程的支持:通过 Spring 提供的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。
  • 方便集成各种优秀框架:Spring提供了对各种优秀框架(如 Struts,Hibernate、MyBatis)等的直接支持。简化框架的使用。Spring 像插线板一样,其他框架是插头,可以容易的组合到一起。

2.2缺点

  • 最大的缺点就是:配置繁琐,启动慢
  • 经常要考虑第三方工具的兼容性
  • 项目的依赖管理耗时耗力

3.框架学习什么?

Spring最主要的学习内容:两个核心Ioc+Aop
Spring框架是一个软件,其它人写好的软件,所以我们要掌握的就是:

  • 1.IOC :Inversion Of Control 控制反转
    2.DI:Dependency Injection 依赖注入: 本质就是给属性赋值
    DI是依附在IOC的基础上 才得以实现
    3.AOP Aspect Oriented Programming 面向切面的编程
  • 知道框架能做什么, mybatis–访问数据库, 对表中的数据执行增删改查。
  • 框架的语法, 框架要完成一个功能,需要一定的步骤支持的,
  • 框架的内部实现, 框架内部怎么做。 原理是什么。
  • 通过学习,可以实现一个框架

4.Spring框架做什么?

目的:管理对象

Spring的核心思想是IOC(控制反转),把对象的控制权给了Spring,(底层是通过反射)即:不再需要程序员去显式地new一个对象,而是让Spring框架帮你来完成这一切。

IOC控制反转:(Inversion Of Control),即就是:将对象的控制权从自己new改为跟Spring要;
  • 最常见的方式:DI:依赖注入Dependency Injection;
  • 还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

5.Spring之IoC

5.1核心概念

  • IoC (Inversion of Control) :控制反转, 是一个理论,概念,思想。描述的:把对象的创建,赋值,管理工作都交给代码之外的容器实现, 也就是对象的创建是有其它外部资源完成。目的就是减少对代码的改动, 也能实现不同的功能。 实现解耦合。
    • 控制: 创建对象,对象的属性赋值,对象之间的关系管理。
    • 反转: 把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。 由容器代替开发人员管理对象。创建对象,给属性赋值。
    • 正转:由开发人员在代码中,使用new 构造方法创建对象, 开发人员主动管理对象。
  • 容器:是一个服务器软件, 一个框架(spring就是一个容器,帮我们创建对象,管理对象之间的关系)

5.2 IoC的技术实现

DI 是ioc的技术实现

  • DI(Dependency Injection):依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建,赋值,查找都由容器内部实现。
  • spring是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制。因此只需要传一个类名,Spring就可以创建对象。
  • spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象。

5.3 完成IoC的步骤

在这里插入图片描述

  1. 添加依赖。
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

2.创建类、接口、实现类。Spring在MVC三层架构中是针对service层的框架。

​ 3.Spring配置文件。通常命名为:applicationContext.xml。该文件类似Servlet的web.xml,在配置文件中注册类,这样Spring才能完成IOC

<?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">

    <!--告诉spring创建对象
        声明bean , 就是告诉spring要创建某个类的对象
        id:对象的自定义名称,唯一值。 spring通过这个名称找到对象
        class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)

        spring就完成 SomeService someService = new SomeServiceImpl();
        spring是把创建好的对象放入到map中, spring框架有一个map存放对象的。
           springMap.put(id的值, 对象);
           例如 springMap.put("someService", new SomeServiceImpl());

        一个bean标签声明一个对象。
    -->
    <bean id="someService" class="com.xd.service.impl.SomeServiceImpl"></bean>

    <!--
        bean标签的scope属性:
            prototype:表示可以一次创建多个该类型对象,即多例
            singleton:默认值,表示一次只能创建一个该类型对象,即单例
            单例模式下,对象是在工厂初始化的时候创建的。多例模式是在工厂初始化之后,获取对象的时候创建的。
    -->
    <bean id="someService1" class="com.xd.service.impl.SomeServiceImpl" scope="prototype"></bean>

    <!--
       spring能创建一个非自定义类的对象吗, 创建一个存在的某个类的对象。
    -->
    <bean id="myDate" class="java.util.Date"></bean>
</beans>
<!--    
   spring的配置文件
   1.beans : 是根标签,spring把java对象成为bean。
   2.spring-beans.xsd 是约束文件,和mybatis指定  dtd是一样的。都是用来控制标签里面出现的内容
-->

4. 测试类中创建Spring容器,调用Spring容器中的方法可以创建对象、获取对象的信息。

@Test
public void test02(){
    //使用spring容器创建的对象
    //1.指定spring配置文件的名称
    String config="applicationContext.xml";
    //2.创建表示spring容器的对象, ApplicationContext
    // ApplicationContext就是表示Spring容器,通过容器获取对象了
    // ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
    ApplicationContext ac = new ClassPathXmlApplicationContext(config);

    //从容器中获取某个对象, 你要调用对象的方法
    //getBean("配置文件中的bean的id值")
    SomeService service = (SomeService) ac.getBean("someService");

    //使用spring创建好的对象
    service.doSome();
}

/*
以下代码的执行原理:通过ClassPathXmlApplicationContext创建容器对象,创建容器对象的同时,ClassPathXmlApplicationContext会根据配置文件的路径去解析配置文件,解析的过程会将配置文件中所有<bean>标签中的类创建对象,默认调用无参构造方法,之后将创建好的对象以及bean标签的id保存在map中,其中id为key。在测试文件中可以调用容器对象ac的getBean方法通过id获取创建好的对象,要强转,然后调用对应方法。
*/
public void test06(){
	String path = "applicationContext.xml";
    ApplicationContext ac = new ClassPathXmlApplicationContext(path);
    Date nowTime = (Date)ac.getBean("myDate");
    System.out.println(nowTime);
}

注意:

  • ApplicationContext是一个接口,有多个实现类,通常使用ClassPathXmlApplicationContext。
  • spring默认创建对象的时间:创建spring的容器时,会创建配置文件中的所有的对象。并把这些对象放到springMap中,之后通过bean标签中的id获取创建好的对象 spring创建对象:默认调用的是无参数构造方法。

5.4 Spring容器对象的方法

//创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//根据bean标签的id获取创建好的对象,getBean返回Object类型,要强转。通过service调用该类的方法
SomeService service = (SomeService) ac.getBean("someService");
//获取容器中定义的对象的数量
int nums = ac.getBeanDefinitionCount();
//容器中每个定义的对象的名称,知道了对象的名称,就可以通过getBean获取创建好的对象。
String[] names = ac.getBeanDefinitionNames();

5.5 IoC的依赖注入:DI

  • 依赖就是属性,注入就是赋值。
  • 注入的方式有set注入以及构造注入,也就是对应正转里的通过类的set方法给对象赋值,以及通过构造方法给类属性赋值。
  • 使用set注入,Spring是根据属性名去寻找对应的set方法并执行,与有没有属性,set方法中写什么内容无关。Spring只是负责找到set方法并执行。set注入也分为简单类型的注入以及引用类型的注入。
    在这里插入图片描述

具体实现:

 <?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"
  <!--声明student对象
        注入:就是赋值的意思
        简单类型: spring中规定java的基本数据类型和String都是简单类型。
        di:给属性赋值
        1. set注入(设值注入) :spring调用类的set方法, 你可以在set方法中完成属性赋值
         1)简单类型的set注入
            <bean id="xx" class="yyy">
               <property name="属性名字" value="此属性的值"/>
               一个property只能给一个属性赋值
               <property....>
            </bean>

         2) 引用类型的set注入 : spring调用类的set方法
           <bean id="xxx" class="yyy">
              <property name="属性名称" ref="bean的id(对象的名称)" />
           </bean>

        2.构造注入:spring调用类有参数构造方法,在创建对象的同时,在构造方法中给属性赋值。
          构造注入使用 <constructor-arg> 标签
          <constructor-arg> 标签:一个<constructor-arg>表示构造方法一个参数。
          <constructor-arg> 标签属性:
             name:表示构造方法的形参名
             index:表示构造方法的参数的位置,参数从左往右位置是 0 , 1 ,2的顺序
             value:构造方法的形参类型是简单类型的,使用value
             ref:构造方法的形参类型是引用类型的,使用ref

        注意:Spring的配置文件中不用考虑bean标签的顺序,因为Spring很智能,会二次扫描
    -->
	
    <!--set注入-->
    <bean id="myStudent" class="com.xd.ba02.Student">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
        <property name="email" value="zhangsan@qq.com"/>
        <!--引用类型,注意引用注入,要先要在bean中定义一个引用对象,将该对象id作为ref的值。-->
        <property name="school" ref="mySchool"/><!--setSchool(mySchool)-->
    </bean>

    <!--声明School对象-->
    <bean id="mySchool" class="com.xd.ba02.School">
        <property name="name" value="西安电子科技大学"/>
        <property name="address" value="西安市雁塔区"/>
    </bean>
    
    <!--使用name属性实现构造注入-->
    <bean id="myStudent" class="com.xd.ba03.Student">
        <!--
            实现原理:Spring扫描到该bean,看到他里面是constructor-arg标签,并且是三个该标签
            就知道是构造注入,并且去com.xd.ba03.Student类中找含有三个参数的有参构造方法,进行赋值。
            与set注入同理:Spring只是负责找有参构造方法,然后去执行,但是构造方法的声明以及方法体是由我们写的。
            有参构造方法声明了只能保证Spring找到了,不会报异常
            但是如果方法体中没有赋值,结果就是:Student对象:Student{name='null', age=0, school=null}
        -->
        <constructor-arg name="name" value="张三"/>
        <constructor-arg name="age" value="20"/>
        <constructor-arg name="school" ref="mySchool"/>
    </bean>

    <!--使用index属性-->
    <bean id="myStudent1" class="com.xd.ba03.Student">
        <constructor-arg index="0" value="李四"/>
        <constructor-arg index="1" value="22"/>
        <constructor-arg index="2" ref="mySchool"/>
    </bean>

    <!--省略index-->
    <bean id="myStudent2" class="com.xd.ba03.Student">
        <constructor-arg value="李四"/>
        <constructor-arg value="22"/>
        <constructor-arg ref="mySchool"/>
    </bean>

    <!--声明School对象-->
    <bean id="mySchool" class="com.xd.ba03.School">
        <property name="name" value="西安xxx大学"/>
        <property name="address" value="西安市雁塔区"/>
    </bean>

    <!--创建File,使用构造注入-->
    <!--构造注入创建文件对象-->
    <bean id="myFile" class="java.io.File">
        <constructor-arg name="parent" value="F:\计算机\Java学习\SSM\04-Spring\源码\ch02-di-xml"/>
        <constructor-arg name="child" value="readme.txt"/>
    </bean>

5.6 基于注解的di(重点)

  • 基于注解的di: 通过注解完成java对象创建,属性赋值
  • 使用注解的步骤:
    1. 加入maven的依赖 spring-context ,在你加入spring-context的同时, 间接加入spring-aop的依赖。使用注解必须使用spring-aop依赖
    2. 在类中加入spring的注解(多个不同功能的注解)
    3. 在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
  • 组件扫描器(component-scan):组件就是java对象。使用方式实在spring配置文件中引入组件扫描器。
<!--声明组件扫描器(component-scan),组件就是java对象
        base-package:指定注解在你的项目中的包名。
        component-scan工作方式: spring会扫描遍历base-package指定的包,
           把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值。

       加入了component-scan标签,配置文件的变化:
        1.加入一个新的约束文件spring-context.xsd
        2.给这个新的约束文件起个命名空间的名称
    -->
<context:component-scan base-package="com.xd.ba01"/>
  • 学习的注解:@Component、@Respotory、@Service、@Controller、@Value、@Autowired、@Qualifier、@Resource

5.6.1 @Component注解

@Component: 创建对象的, 等同于的功能。

  • 语法格式:@Component(value = “myStudent”) 等同于
    • 属性:value 就是对象的名称,也就是bean的id值,value的值是唯一的,创建的对象在整个spring容器中就一个;
    • 位置:在类的上面
//使用value属性,指定对象名称
//@Component(value = "myStudent")
//不指定对象名称,由spring提供默认名称: 类名的首字母小写
//@Component

@Component("myStudent")  //常用
public class Student {
    private String name;
    private int age;

    public Student() {
        System.out.println("student无参构造方法执行");
    }

	setter

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

5.6.2 @Respotory、@Service、@Controller 注解

  • @Respotory、@Service、@Controller这三个注解与Component功能类似,都是创建对象。但是又有其特殊的用途,是给项目的对象分层的。
  • @Repository(用在持久层类的上面) : 放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库的。
  • @Service(用在业务层类的上面):放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务等功能的。
  • @Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求的处理结果。
  • 对于@Component、@Respotory、@Service、@Controller。毋庸置疑的是,持久层dao用@Respotory、业务层用@Service、页面层用@Controller。对于其它不在这三层的类,但是又想创建对象,就用@Component注解。

5.6.3 @Value

  • @Value注解的作用是给对象简单类型属性赋值
  • 属性:@Value注解里的值必须是String类型,赋的值要用双引号括起来
  • 位置:
    1. 在属性定义的上面,无需set方法,推荐使用。底层用反射快。
    2. 在set方法的上面使用,调set方法。
@Component("myStudent")
public class Student {
    @Value("张三")
    private String name;
    
    @Value("20")
    private int age;
    
    //@Value("20") 调set方法
    public void setAge(int age) {
        System.out.println("student的set方法执行了");
        this.age = age;
    }
}

5.6.4 @Autowired

  • @Autowired注解的作用是给对象引用类型属性赋值。使用的是自动注入原理 ,支持byName, byType。默认byType。

  • 位置:

    1. 在属性定义的上面,无需set方法, 推荐使用
    2. 在set方法的上面
    @Autowired  //按byType注入
    private School school;
    
  • 如果要使用byName方式,需要做的是:

    1. 在属性上面加入@Autowired
    2. 在属性上面加入@Qualifier(value=“bean的id”) :表示使用指定名称的bean完成赋值。
    @Component("mySchool")
    public class School {
    }
    
    @Autowired
    @Qualifier(value = "mySchool") //mySchool为id
    private School school;
    
  • @Autowired注解的request属性,是一个boolean类型的,默认true。一般使用true,方便排错。

    • required=true:表示引用类型赋值失败,程序报错,并终止执行。
    • required=false:引用类型如果赋值失败, 程序正常执行,引用类型是null,不建议用,因为赋值为null以后会出空指针异常。
    //@Autowired(required = true) 默认
    //@Autowired(required = false)不报错,不建议用
    @Autowired
    @Qualifier(value = "mySchool")
    private School school;
    

5.6.5 @Resource

  • @Resource: 来自jdk中的注解,spring框架提供了对这个注解的功能支持,完成引用类型的自动注入,支持byName,byType。默认byName

  • 位置:

    1. 在属性定义的上面,无需set方法,推荐使用。
    2. 在set方法的上面
    @Component("school")
    public class School {
    }
        
    @Resource //默认是byName: 先使用byName自动注入,如果byName赋值失败,再使用byType
    private School school;
    
  • @Resource只使用byName方式,需要增加一个属性 name,name的值是bean的id(名称)

    @Resource(name = "mySchool")
    private School school;
    

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

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

相关文章

Kubernetes技术与架构-调度 1

Kubernetes技术与架构集群对Pod的资源调度策略分为三个部分&#xff0c;其中包括匹配调度、优先调度以及终止调度&#xff0c;匹配调度是指将Pod匹配到适合、指定的Node服务器节点中运行&#xff0c;优先调度是指终止优先级低的Pod而优先匹配优先级高的Pod到适合的Node服务器节…

通过阿里云服务器实现访问自己的网站,域名绑定教程

人的梦想&#xff0c;永远不会结束&#xff01;——黑胡子 请把那把刀给我吧&#xff01;我要会连她的份也一起努力的&#xff0c;我要成为世界第一的大剑客&#xff0c;我要让我的名字&#xff0c;响彻天堂&#xff01;——索隆 准备&#xff1a;服务器&#xff0c;域名&…

双指针训练

1.原理 双指针是一种解题常用方法&#xff0c;常用于将数组按照某种要求进行分块/划分&#xff0c;这里的指针对于数组来说&#xff0c;可以替换成下标&#xff08;毕竟使用下标实际上就是用了指针&#xff09;。 1.1.划分区间 通常将这两个指针命名位dest/cur&#xff08;或…

求Top K问题

1.大小根堆解决Top k问题 传统思想&#xff1a;是将容器中的数据进行排序&#xff0c;排序的时间复杂度最差像冒泡是O(n^2),最好像快排是O(nlogn)。 如何在线性时间内O(n)找到Top K的元素呢? 相当于将原始序列遍历一遍就可以找到相应的元素&#xff0c;其实也没有必要将所有…

C语言之函数式宏

目录 函数和数据类型 函数式宏 函数和函数式宏 函数式宏和对象式宏 不带参数的函数式宏 函数式宏和逗号运算符 函数式宏和函数类似并且比函数更加灵活&#xff0c;下面我们就来学习函数式宏的相关内容。 函数和数据类型 我们来编写一个程序&#xff0c;它能计算出所读取…

python蓝桥杯的回形取数

#来源于蓝桥杯的训练 题号是用户登录https://www.lanqiao.cn/problems/1517/learning/?page1&first_category_id1&problem_id1517 根据题目描述可以知道&#xff0c;我们传入的是一个矩阵。 在这里我们使用列表来实现矩阵。 那么&#xff0c;我们直接看代码 dir …

超详细 | 黏菌算法原理、实现及其改进与利用(Matlab/Python)

测试函数为F15 在MATLAB中执行程序结果如下&#xff1a; 在Python中执行程序结果如下&#xff1a; 众所周知&#xff0c;麻雀搜索算法SSA是2020年由东华大学沈波教授团队提出[1]的一种性能十分优异的优化算法&#xff0c;而最近作者发现&#xff0c;在2020年还提出了一个优…

腾讯云:AI云探索之路

随着科技的飞速发展&#xff0c;人工智能(AI)云计算领域日益显现出其巨大的潜力和价值。在这个充满挑战和机遇的领域&#xff0c;腾讯云凭借其卓越的技术和创新能力&#xff0c;取得了令人瞩目的成果。本文将深入探讨腾讯云在AI云计算领域的优势&#xff0c;以及其为人工智能发…

Post Json数据与Form表单数据转换器

具体请访问&#xff1a;在线Json转Form表单参数工具

python绘制gif动图--避免收费拒绝水印

在cp源码解读-CSDN博客文章浏览阅读341次,点赞4次,收藏6次。coreutils:cp源代码分析https://blog.csdn.net/zhaiminlove/article/details/135026160中为了直观的表达文件是如何一步步的copy的,就想到了做一个gif,但是从来没弄过,一下有点麻爪了。 首先想到的是百度、Goog…

孩子都能学会的FPGA:第三十三课——用FPGA实现一个通用的SPI主机接收模块

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…

C语言指针4

1. #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h>int main() {int a 10;int* p &a;//一级指针int** pp &p;//二级指针return 0; }上述代码中p的类型是int* pp的类型是int** 2.int* arr[5]; 数组arr的每个元素是整形指针 3.定义一个变量时,去掉变…

报数游戏C语言

分析:掌握数字移动的规律&#xff0c;以及判断&#xff0c;我们可以用一个二维数组来记录每一个人说的数字&#xff0c;就像第一张图片一样&#xff0c;西安向右边移动&#xff0c;再向左下移动&#xff0c;再向左边移动&#xff0c;在向右边移动&#xff0c;在可以用一个数组来…

3 - Electron BrowserWindow对象 关于窗口

优雅的打开应用~ 当加载缓慢&#xff0c;打开应用的一瞬间会出现白屏&#xff0c;以下方法可以解决 const mainWindow new BrowserWindow({ show: false }) mainWindow.once(ready-to-show, () > {mainWindow.show() }) 设置背景颜色 const win new BrowserWindow({ b…

比特币即自由

号外&#xff1a;教链内参12.15《疯狂的铭文》 文 | Ross Ulbricht. 原文标题&#xff1a;Bitcoin Equals Freedom. 2019.9.25 在中本聪发明比特币后的头一年左右&#xff0c;发生了一些特别的事情&#xff0c;不仅没有人预料到&#xff0c;甚至很多人认为不可能。试着想象一下…

【Python从入门到进阶】44、Scrapy的基本介绍和安装

接上篇《43.验证码识别工具结合requests的使用》 上一篇我们学习了如何使用验证码识别工具进行登录验证的自动识别。本篇我们开启一个新的章节&#xff0c;来学习一下快速、高层次的屏幕抓取和web抓取框架Scrapy。 一、Scrapy框架的背景和特点 Scrapy框架是一个为了爬取网站数…

Python:Jupyter

Jupyter是一个开源的交互式计算环境&#xff0c;由Fernando Perez和Brian Granger于2014年创立。它提供了一种方便的方式来展示、共享和探索数据&#xff0c;并且可以与多种编程语言和数据格式进行交互。Jupyter的历史可以追溯到2001年&#xff0c;当时Fernando Perez正在使用P…

开源免费图床Lychee本地部署搭建个人云图床并公网访问【内网穿透】

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 图床作为图片集中存放的服务网站&#xff0c;可以看做是云存储的一部分&#xff0c;既可…

LeetCode(64)分隔链表【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 分隔链表 1.题目 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 示…

加油站“变身”快充站,探讨充电新模式——安科瑞 顾烊宇

摘要&#xff1a;新能源汽车规模化发展的同时&#xff0c;充电不便利的痛点愈发明显。在未来的新能源汽车行业发展当中&#xff0c;充电的矛盾要远远大于造车的矛盾&#xff0c;解决好充电的问题成为电动汽车行业发展的一个突出问题。解决充电补能问题&#xff0c;重要的方式之…