Spring与Spring Bean

Spring 原理

它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可
以和其他的框架无缝整合。

Spring 特点

轻量级
控制反转
面向切面
容器
框架集合

在这里插入图片描述
Spring 核心组件
在这里插入图片描述
Spring 总共有十几个组件核心容器(Spring core) Spring上下文(Spring context)Spring面向切面编程(Spring AOP)Spring DAO模块Spring ORM模块Spring Web模块Spring MVC框架(Spring WebMVC)。

**但是真正核心的组件只有三个Core、Context 和 Bean。**它们构建起了整个 Spring的骨骼架构没有它们就不可能有 AOP、Web 等上层的特性功能。

Bean
通过Bean注入类的属性和参数,同过Bean实现类的实例化。
Spring 就是面向 Bean 的编程(BOP,Bean Oriented Programming),Bean 在 Spring 中才是真正的主角。
Bean在Spring 中作用就像 Object 对 OOP 的意义一样,没有对象的概念就像没有面向对象编程,Spring 中没有 Bean 也就没有 Spring 存在的意义。
就像一次演出舞台都准备好了但是却没有演员一样。为什么要 Bean 这种角色 Bean 或者为何在 Spring 如此重要,
这由 Spring 框架的设计目标决定,Spring 为何如此流行,我们用 Spring 的原因是什么,
想想你会发现原来 Spring 解决了一个非常关键的问题他可以让你把对象之间的依赖关系转而用配置文件来管理。
也就是他的依赖注入机制。而这个注入关系在一个叫 Ioc 容器中管理,那 Ioc 容器就是被 Bean 包裹的对象。
Spring 正是通过把对象包装在 Bean 中而达到对这些对象的管理以及一些列额外操作的目的。

Core
Spring框架最基础的部分,它提供了依赖注入(DependencyInjection)特征来实现容器对Bean的管理。
采用Factory(工厂模式)实现了IoC(控制反转)将应用的配置和依赖性规范与实际的应用程序代码分开;
提供了框架的基本组成部分包括控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)功能。

Context
是一个配置文件,向Spring框架提供上下文信息;
构建与core封装包基础上的context封装包,提供了一种框架式的对象访问方法。
Context 作为 Spring 的 Ioc 容器

细说Bean
从广义上 Spring 注解可以分为两类:

一类注解是用于注册 Bean

假如 IoC
容器是一间空屋子,首先这间空屋子啥都没有,我们要吃大餐,我们就要从外部搬运食材和餐具进来。这里把某一样食材或者某一样餐具搬进空屋子的操作就相当于每个注册
Bean 的注解作用类似。注册 Bean 的注解作用就是往 IoC容器中放(注册)东西!

用于注册 Bean 的注解:比如
@Component、@Repository、@Controller、@Service、@Configuration 这些注解就是用于注册
Bean,放进 IoC 容器中,一来交给 Spring
管理方便解耦,二来还可以进行二次使用,啥是二次使用呢?这里的二次使用可以理解为:在你开始从外部搬运食材和餐具进空屋子的时候,一次性搬运了猪肉、羊肉、铁勺、筷子四样东西,这个时候你要开始吃大餐,首先你吃东西的时候肯定要用筷子或者铁勺,别说你手抓,只要你需要,你就会去找,这个时候发现你已经把筷子或者铁勺放进了屋子,你就不同再去外部拿筷子进屋子了,意思就是
IoC 容器中已经存在,就可以直接拿去用,而不必再去注册!而拿屋子里已有的东西的操作就是下面要讲的关于使用 Bean 的注解!

一类注解是用于使用 Bean

用于使用 Bean 的注解:比如 @Autowired、@Resource
注解,这些注解就是把屋子里的东西自己拿来用,如果你要拿,前提一定是屋子(IoC)里有的,不然就会报错。比如你要做一道牛肉拼盘需要五头牛做原材料才行,你现在锅里只有四头牛,这个时候你知道,自己往屋子里搬过五头牛,这个时候就直接把屋子里的那头牛直接放进锅里,完成牛肉拼盘的组装。是的这些注解就是需要啥,只要容器中有就往容器中拿,就是这么豪横!而这些注解又有各自的区别,比如
@Autowired 用在筷子上,这筷子你可能想用木质的,或许只想用铁质的,@Autowired 作用在什么属性的筷子就那什么筷子,即是按类型的。
@Resource 如果用在安格斯牛肉上面,就指定要名字就是安格斯牛肉的牛肉,即是按照名字的。

一、定义
Bean 是 Spring 框架中最核心的两个概念之一(另一个是面向切面编程 AOP)

Spring 官方文档对 bean 的解释是:

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container.

翻译过来就是:

在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。bean 是由Spring IoC
容器实例化、组装和管理的对象。

从上面翻译过来意思来看:

bean 是对象,一个或者多个不限定
bean 由 Spring 中一个叫 IoC 的东西管理的
我们的应用程序由一个个 bean 构成

控制反转(IoC)
控制反转英文全称:Inversion of Control,简称就是 IoC。控制反转通过依赖注入(DI)方式实现对象之间的松耦合关系。程序运行时,依赖对象由辅助程序动态生成并注入到被依赖对象中,动态绑定两者的使用关系。Spring IoC 容器就是这样的辅助程序,它负责对象的生成和依赖的注入,然后再交由我们使用。

1、什么是依赖注入与控制反转呢?先通过一个例子来理解一下
首先有一个类叫做 Student,里面有两个成员变量分别是 id 和 name,并提供 set、get方法。

public class Student {
    private Integer id;
    private String name;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

另外一个类叫做 StudentManager

public class StudentManager {
    private Student student;
 
    public void setStudent(Student student) {
        this.student = student;
    }
 
    public void show() {
        System.out.println(student.getId());
        System.out.println(student.getName());
    }
}

这个 StudentManager 类有个成员是 Student 的一个对象,然后它的 show 方法能够打印这个 student 的 id 以及 name,并提供了 setStudent 方法初始化 Student 对象。我们可以说,StudentManager(被依赖对象) 是依赖于 Student(依赖对象)的。

    有一个问题,StudentManager 与 Student 之间的耦合非常紧密,假如我们还没有来的及对 StudentManager 的 student 绑定对象,却调用了 show 方法的话,那么程序将会抛出空指针异常。所以 Spring 提供了一套叫做控制反转与依赖注入这套机制,目的就是为了解耦。

    在 Spring 中,**你不需要自己创建对象,**你只需要告诉 Spring,哪些类我需要创建出对象,然后在启动项目的时候 Spring 就会自动帮你创建出该对象,并且只存在一个类的实例。这个类的实例在 Spring 中被称为 Bean。**而这种模式,我们称之为“单例模式”。也就是一个类只有一个实例的意思。**

那么 Spring 是靠什么来了解究竟哪些类需要帮我们创建呢,这里介绍最常用的两种方式------Java 注解配置,Java 代码配置。之前还有 XML 配置等,但是之前的现在已经不推荐使用了。

    首先介绍的是 Java 注解配置,这是最简单也是最常用的一种方式。

在这里插入图片描述
以上四种声明方式效果完全一致,使用不同的关键词是为了给阅读的人能够快速了解该类属于哪一层。

    使用方法为:在定义的实体类前使用该注解。让我们看下面一段代码
@Component
public class Student {
    private Integer id;
    private String name;
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

我们在刚才的 Student 类前面,加上了 @Component 注解,成功告诉 Spring:你要在项目创建运行时帮我创建 Student 类的 Bean (对象)。

    好了,这时候添加“依赖”就已经做完了,但是还没完,我们虽然让 Spring 帮我们创建了对象,但是 StudentManager 怎么知道这个对象在哪呢?所以接下来,我们要告诉 StudentManager 刚才 Spring 帮我们创建的 Bean (对象)到底在哪,也就是使用(“注入”)这个 Bean。

我们来看看注入注解的语法:
在这里插入图片描述
使用方法:在我们需要注入依赖的成员变量前使用该注解,看一下下面一段代码

@Component
public class StudentManager {
    @Autowired
    private Student student;
 
    public void show() {
        System.out.println(student.getId());
        System.out.println(student.getName());
    }
}

可以看到,在声明成员变量 Student 的前面我们使用了 @Autowired,所以 Spring 会自动帮我们使用(注入)一个 Bean,我们就再也不用担心忘记绑定对象而出现空指针了。但是可以发现,虽然我们告诉了 Spring 哪些类是需要添加依赖,哪些类是需要注入 Bean,但是 Spring 还需要我们做一次配置,来真正完成这样一个操作。

2、让 Spring 控制类构建过程
不用 new,让 Spring 控制 new 过程。在 Spring 中,我们基本不需要 new 一个类,这些都是让 Spring 去做的。Spring 启动时会把所需的类实例化对象,如果需要依赖,则先实例化依赖,然后实例化当前类。因为依赖必须通过构建函数传入,所以实例化时,当前类就会接收并保存所有依赖的对象。这一步也就是所谓的依赖注入。

3、这就是 IOC
在 Spring 中,类的实例化、依赖的实例化、依赖的传入都交由 Spring Bean 容器控制,而不是用 new 方式实例化对象、通过非构造函数方法传入依赖等常规方式。实质的控制权已经交由程序管理,而不是程序员管理,所以叫控制反转。

@Bean 注解的使用
1、使用说明
@Bean 注解作用在方法上,产生一个 Bean 对象,然后这个 Bean 对象交给 Spring 管理,剩下的你就不用管了。产生这个 Bean 对象的方法 Spring 只会调用一次,随后这个 Spring 将会将这个 Bean 对象放在自己的 IOC 容器中。
@Bean 方法名与返回类名一致,首字母小写。
@Component、@Repository、@Controller、@Service 这些注解只局限于自己编写的类,而 @Bean 注解能把第三方库中的类实例加入 IOC 容器中并交给 Spring 管理。
@Bean 一般和 @Component 或者 @Configuration 一起使用
2、Bean 名称
2.1、默认情况下 Bean 名称就是方法名(首字母小写),比如下面 Bean 名称便是 myBean

@Bean
public MyBean myBean() {
    return new MyBean();
}

2.2、@Bean 注解支持设置别名。比如下面除了主名称 myBean 外,还有个别名 myBean1(两个都可以使用)

@Bean("myBean1")
public MyBean myBean() {
    return new MyBean();
}

2.3、@Bean 注解可以接受一个 String 数组设置多个别名。比如下面除了主名称 myBean 外,还有别名 myBean1、myBean2(三个都可以使用)

@Bean({"myBean1","myBean2"})
public MyBean myBean() {
    return new MyBean();

3、@Bean 与其他注解产生的火花
@Bean 注解常常与 @Scope、@Lazy、@DependsOn 和 @link Primary 注解一起使用

3.1、@Profile 注解
为在不同环境下使用不同的配置提供了支持,如开发环境和生产环境的数据库配置是不同的

@Bean
@Profile("!dev")  // 不是dev环境的能使用这个bean
public MyBean myBean() {
    MyBean myBean = new MyBean();
    myBean.setPort("8080");
    return myBean;
}

3.2、@Scope 注解
在 Spring 中对于 bean 的默认处理都是单例的,我们通过上下文容器.getBean方法拿到 bean 容器,并对其进行实例化,这个实例化的过程其实只进行一次,即多次 getBean 获取的对象都是同一个对象,也就相当于这个 bean 的实例在 IOC 容器中是 public 的,对于所有的 bean 请求来讲都可以共享此 bean。@Scope 注解将其改成 prototype 原型模式(每次获取 Bean 的时候会有一个新的实例)

@Bean
@Scope("prototype")
public MyBean myBean() {
    MyBean myBean = new MyBean();
    myBean.setPort("8080");
    return myBean;
@SpringBootApplication
@MapperScan("com.example.quartzdemo.dao")//使用MapperScan批量扫描所有的Mapper接口;
public class QuartzDemoApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(QuartzDemoApplication.class, args);
        MyBean myBean = (MyBean) context.getBean("myBean");
        System.out.println(myBean);
        MyBean myBean2 = (MyBean) context.getBean("myBean");
        System.out.println(myBean2);
    }
}

打印输出结果:

com.example.quartzdemo.config.MyBean@49601f82
com.example.quartzdemo.config.MyBean@23e44287

将 @Scope(“prototype”) 删除掉,再运行启动类,打印结果如下:

com.example.quartzdemo.config.MyBean@4cdd2c73
com.example.quartzdemo.config.MyBean@4cdd2c73

3.3、@Lazy 注解:
在 Spring 框架中,默认会在启动时会创建所有的 Bean 对象,但有些 bean 对象假如长时间不用,启动时就创建对象,会占用其内存资源,从而造成一定的资源浪费,此时我们可以基于懒加载策略延迟对象的创建。

@Bean
@Lazy
public MyBean myBean() {
MyBean myBean = new MyBean();
myBean.setPort(“8080”);
return myBean;

Bean 的生命周期
  对于普通的 Java 对象,new 的时候会去创建对象,而当它没有任何引用的时候则被垃圾回收机制回收。相较于前者,由Spring IoC 容器托管的对象,它们的生命周期完全由容器控制。Spring 中每个 Bean 的生命周期如下:
在这里插入图片描述
总体分为四个阶段:

  ①实例化 CreateBeanInstance
  ②属性赋值 PopulateBean
  ③初始化 Initialization
  ④销毁 Destruction**

其中多个增强接口贯穿了这四个阶段!

三、SpringBean生命周期中的增强接口PostProcessor:
在上图里有多种后置处理器接口,它们贯穿了Bean的生命周期,且它们的实现类都会在SpringIOC容器进行初始化的时候进行实例化,让我们来做一个区分:
在这里插入图片描述
四、实例展示
SpringBeanDemo

package com.rx.spring;
 
import com.rx.spring.domain.Person;
import com.rx.spring.domain.Student;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
public class SpringBeanDemo {
    public static void main(String[] args) throws Exception {
        System.out.println("****开始启动****");
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
        System.out.println("****启动完毕****");
        Person person = applicationContext.getBean("person", Person.class);
        Student student = applicationContext.getBean("student", Student.class);
 
        System.out.println("=============================================");
        System.out.println("person:" + person);
        System.out.println("student:" + student);
        person.destroy();
 
        System.out.println("============现在开始关闭容器======================");
        applicationContext.registerShutdownHook();
    }
}

Config

package com.rx.spring;
 
import org.springframework.context.annotation.*;
 
@Configuration
@ComponentScan("com.rx.spring")
@ImportResource("classpath:spring.xml")
public class Config {
     
}

Person

package com.rx.spring.domain;
 
import lombok.Data;
import org.springframework.beans.factory.DisposableBean;
 
@Data
public class Person implements DisposableBean {
    private String name;
    private String address;
    private String tel;
 
    public Person(String name, String address, String tel) {
        System.out.println("Person--->>>有参构造方法");
        this.name = name;
        this.address = address;
        this.tel = tel;
    }
 
    public Person() {
        System.out.println("Person--->>>无参构造方法");
    }
 
    private void raoInitMethod() {
        System.out.println("person--->>>InitMethod...");
    }
 
    private void raoDestroyMethod() {
        System.out.println("person--->>>DestroyMethod...");
    }
 
    @Override
    public void destroy() throws Exception {
        System.out.println("【DisposableBean接口】调用DisposableBean.destroy()");
    }
}

Student

package com.rx.spring.domain;
 
import lombok.Data;
import org.springframework.beans.factory.DisposableBean;
 
@Data
public class Student implements DisposableBean {
    private String username;
    private String password;
 
    public Student(String username, String password) {
        System.out.println("student--->>有参构造方法");
        this.username = username;
        this.password = password;
    }
    public Student() {
        System.out.println("student--->>>无参构造方法");
    }
 
    private void raoInitMethod() {
        System.out.println("student--->>>InitMethod...");
    }
 
    private void raoDestroyMethod() {
        System.out.println("student--->>>DestroyMethod...");
    }
 
    @Override
    public void destroy() throws Exception {
        System.out.println("【DisposableBean接口】调用DisposableBean.destroy()");
    }
}

RaoInstantiationAwareBeanPostProcessor

package com.rx.spring.beanpostprocessor;
 
import com.rx.spring.domain.Person;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Component;
 
@Component
public class RaoInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("person".equals(beanName) || "student".equals(beanName)) {
            System.out.println(beanName + "--->>>InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation....");
        }
        return null;
    }
 
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("person".equals(beanName) || "student".equals(beanName)) {
            System.out.println(beanName + "--->>>InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation....");
        }
        return bean instanceof Person;
    }
 
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "--->>>InstantiationAwareBeanPostProcessor.postProcessProperties...");
        PropertyValue[] propertyValues = pvs.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues) {
            if ("name".equals(propertyValue.getName())) {
                propertyValue.setConvertedValue("改后rx");
            }
        }
        return pvs;
    }
}

RaoBeanPostProcessor


package com.rx.spring.beanpostprocessor;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
 
@Component
public class RaoBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("person".equals(beanName) || "student".equals(beanName)) {
            System.out.println(beanName + "--->>>BeanPostProcessor.postProcessBeforeInitialization...");
        }
        return bean;
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("person".equals(beanName) || "student".equals(beanName)) {
            System.out.println(beanName + "--->>>BeanPostProcessor.postProcessAfterInitialization....");
        }
        return bean;
    }
}

spring.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">
 
    <bean id ="person" class="com.rx.spring.domain.Person" init-method="raoInitMethod" destroy-method="raoDestroyMethod">
        <property name="name" value="rx"/>
        <property name="address" value="beijing"/>
        <property name="tel" value="157********"/>
    </bean>
 
    <bean id ="student" class="com.rx.spring.domain.Student" init-method="raoInitMethod" destroy-method="raoDestroyMethod">
        <property name="username" value="rx"/>
        <property name="password" value="1234"/>
    </bean>
 
</beans>

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

RN 使用react-navigation写可以滚动的横向导航条(expo项目)

装包&#xff1a; yarn add react-navigation/material-top-tabs react-native-tab-view npx expo install react-native-pager-view import React from react import { View, Text, ScrollView, SafeAreaView } from react-native import { Icon } from ../../../../../compo…

python编辑器安装与配置,python用哪个编辑器好用

大家好&#xff0c;给大家分享一下python编辑器pycharm安装教程&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 哪些python的编程软件值得推荐&#xff1f; 编写python源代码的软件.首推的Pycharm。 PyCharm用于bai一般IDE具备的功能&…

Redis的安装方法与基本操作

目录 前言 一、REDIS概述 二、REDIS安装 1、编译安装 2.yum安装 三、Redis的目录结构 四、基础命令解析 五、在一台服务器上启动多个redis 六、数据库的基本操作 &#xff08;一&#xff09;登录数据库 &#xff08;二&#xff09;基础命令 七、Redis持久化 &#xff08;一&…

每天一个知识点——Normalization

这里结合大模型的学习&#xff0c;主要分析Layer Norm、RMS Norm和Deep Norm的异同&#xff0c;与此同时&#xff0c;究竟是在之前执行Normalization&#xff08;Pre-Norm&#xff09;还是之后执行&#xff08;Post-Norm&#xff09;&#xff0c;也是一个比较喜欢拿来讨论的知识…

ChatGPT会取代搜索引擎吗?BingChat、GoogleBard与ChatGPT区别

目前暂时不会&#xff0c;ChatGPT为代表的聊天机器人很可能会直接集成到搜索中&#xff0c;而不是取代它。微软已经通过Bing Chat和Bing做到了这一点&#xff0c;它将“聊天”选项卡直接放入Bing搜索的菜单中。Google、百度也分别开始尝试通过其AI生成技术将Google Bard、文心一…

Pytest三种运行方式

Pytest 运行方式共有三种&#xff1a; 1、主函数模式 运行所有 pytest.main() 指定模块 pytest.main([-vs],,./testcase/test_day1.py) 只运行testcase 下的test_day1.py 文件 指定目录 pytest.main([-vs]),./testcase) 只运行testcase 目录下的文件 通过nodeid指定用例…

Cmder:从此告别记事本记命令的日子

前言 平时开发中遇到这样那样的命令需要记下来&#xff0c;一般做法是这样。 新建记事本将需要记下的关键命令保存。每次需要使用时&#xff0c;粘贴复制即可。 好像没什么毛病&#xff01;直到遇到了 Cmder。。。 当看到同事分析问题时在 Cmder 里命令快捷键刷刷一顿操作&…

C#实现邮箱验证码

开发环境&#xff1a;C#&#xff0c;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core Web API&#xff0c;163邮箱 1、在163邮箱的设置中开通IMAP/SMTP的服务&#xff0c;授权成功后会弹出一个窗体&#xff08;如下图所示&#xff09;&#xff0c;上面显示了授权密码…

C++ ModBUS TCP客户端工具 qModMaster 介绍及使用

qModMaster工具介绍 QModMaster是一个基于Qt的Modbus主站&#xff08;Master&#xff09;模拟器&#xff0c;用于模拟和测试Modbus TCP和RTU通信。它提供了一个直观的图形界面&#xff0c;使用户能够轻松设置和发送Modbus请求&#xff0c;并查看和分析响应数据。 以下是QModM…

湘大 XTU OJ 1256 湘潭大学 题解(非常详细):枚举

一、链接 1256 湘潭大学 二、题目 题目描述 湘潭大学简称“XTU”&#xff0c;作为即将成为湘大的一份子&#xff0c;怎么不能为湘大添砖加瓦了&#xff1f;现在给你一个字符串&#xff0c;请你计算一下&#xff0c;从中选取字符&#xff0c;最多能组成多少个“XTU”&#x…

v-md-editor自定义锚点(生成目录)数组转树结构

接前两篇博文&#xff0c;最终方案终于定了&#xff0c;也把之前做的编辑器模式给否决了&#xff0c;原因是系统中有老的文档需要平替&#xff0c;因此就不能通过编辑器这种模式了&#xff0c;太麻烦了。 最终方案&#xff1a;线下手动pandoc word转markdown&#xff0c;然后将…

Qt 7. 在自定义类TcpClient类中使用信号槽功能

1. 因为只有QObject类及其子类派生的类才能使用信号和槽机制。 使用信号和槽还必须在类声明的最开始处添加Q_OBJECT宏&#xff0c;在这个程序中&#xff0c;类的声明是自动生成的&#xff0c;已经添加了这个宏。UI类继承自QDialog&#xff0c;QDialog类又继承自QWidget类&…

Oracle-创建PDB

Oracle-创建PDB 创建PDB的方式 从PDB$SEED新建PDB克隆已存在的PDB 本地PDB克隆到同一个CDB中将远程PDB克隆到CDB中将非CDB插入或克隆到CDB中通过插拔的方式创建PDB sql 命令语法 条件 CDB必须open并且read write模式连接CDB$ROOT 用户并且具有CREATEPLUGGABLEDATABASE系统权…

解决android studio妙明奇妙出现的模拟器

1&#xff0c;查看设备 adb devices 2&#xff0c; adb命令断开指定的设备 要断开ADB与特定设备的连接&#xff0c;可以使用以下命令&#xff1a; adb disconnect <设备ID> 将 <设备ID> 替换为您要断开连接的设备的实际ID。设备ID可以在运行 adb devices 命令…

Von Maur, Inc EDI 需求分析

Von Maur, Inc 是一家历史悠久的卖场&#xff0c;成立于19世纪&#xff0c;总部位于美国。作为一家知名的零售商&#xff0c;Von Maur 主要经营高端时装、家居用品和美妆产品。其使命是为顾客提供优质的产品和无与伦比的购物体验。多年来&#xff0c;Von Maur 凭借其卓越的服务…

MySQL SUBSTRING_INDEX() 函数的详细介绍

MySQL SUBSTRING_INDEX() 从给定字符串中返回指定数量的分隔符出现之前的子字符串。 当指定数字为正数时从最终分隔符的左侧返回子字符串&#xff0c;当指定数字为负数时从最终分隔符的右侧返回子字符串。 如果指定的次数大于分隔符的出现次数&#xff0c;则返回的子字符串将…

机器人技术及其影响

目录 1.概念 2.发展 3.应用领域 4.对人类的益处 1.概念 机器人是指能够自主执行任务的机械设备或电子设备。它们通常具有一定的感知、决策和执行能力&#xff0c;能够接收和处理来自外部环境的信息&#xff0c;并做出相应的行动。 机器人的形态和功能各异&#xff0c;可以是…

Netty自定义编码解码器

上次通信的时候用的是自带的编解码器&#xff0c;今天自己实现一下自定义的。 1、自定义一下协议 //协议类 Data public class Protocol<T> implements Serializable {private Long id System.currentTimeMillis();private short msgType;// 假设1为请求 2为响应privat…

JAVA基础补充(Comparable排序接口的实现)

JAVA基础补充&#xff08;Comparable排序接口的实现&#xff09; Comparable接口的实现&#xff1a;没有实现Comparable接口时&#xff0c;取出来的值无法排序如果进行排序&#xff1a;实现接口进行排序&#xff1a;Controller层的实现实体类的实现 复习时间&#xff1a;2023/0…

(学习笔记-进程管理)多线程冲突如何解决

对于共享资源&#xff0c;如果没有上锁&#xff0c;在多线程的环境里&#xff0c;很有可能发生翻车。 竞争与合作 在单核 CPU 系统里&#xff0c;为了实现多个程序同时运行的假象&#xff0c;操作系统通常以时间片调度的方式&#xff0c;让每个进程每次执行一个时间片&#xf…