当前位置: 首页 > news >正文

Spring 框架精髓:从基础到分布式架构的进阶之路

一、概述

(一)Spring框架概念

1.概念:

  • Spring框架是一个用于简化Java企业级应用开发的开源应用程序框架。

2.Spring框架的核心与提供的技术支持:

  • 核心: 
    • IoC控制反转|反转控制:利用框架创建类的对象的技术。 
    • AOP面向切面的编程思想:通过切面类和方法为核心业务提供非核心的业务技术。
  • 本身提供了技术支持: 

提供了表现层框架:SpringMVC

提供了持久层框架:SpringJDBC

提供了整合其它的三方框架和类库的基础。(Spring框架本身使用Maven框架管理项目)。

3.Spring框架本质:管理项目中的对象(即创建对象和维护对象与对象之间的关系)。

4.Spring的优势

5.Spring的架构

(二)Spring框架的IoC容器

1.IoC

概念:

即控制反转,把创建对象的权利交给框架,即将对象的创建、初始化、存储、管理交给Spring容器。

实质:

一种通过描述来生成或者获取对象的技术。

常用概念:

SpringBean:在Spring中把每一个需要管理的对象称之Spring Bean。

SrpingIoC容器:在Spring中管理这些Bean的容器。

管理过程:

第一步:将需要的POJO提前在配置文件中进行描述(程序员负责)。

第二步:Spring会根据配置文件中的描述生成IoC容器并装配Bean(Spring框架负责)。

第三步:需要该Bean的对象时,通过API获取即可(程序员负责)。

管理过程示意图:

2.耦合与解耦

耦合与解耦

所谓耦合:在项目开发时,经常会遇到在一个程序中会new另外一个类的对象,而在new对象时,会造成当前这个程序,严重的依赖于其它对象,会造成程序之间的依赖程度提升,而程序和程序之间的依赖关系被称之为耦合。依赖关系越高,耦合性就越高。 

在项目开发时,我们希望程序和程序之间的耦合程度越低越好。 

解耦:解除对象与对象之间的依赖关系就叫解耦。 

  • 常见的解耦方式 
    • 1.分层开发解耦方式 
      • 开发思想:将程序各组成部分定位于不同层次,达到降低耦合度的目的。 
      • 常见开发模式:工厂模式解耦
    • 2.使用框架解耦方式开发思想:IoC和分层开发。

二、Maven整合Spring常规开发

(一)开发步骤

第一步:导入Spring依赖

第二步:通过xml文件装配类(Spring的Bean配置)

第三步:读取Bean的配置文件

第四步:通过Api获取Bean

方式一:通过装配类的名字获取bean(源文件中)

方式二:通过类的字节码对象获取bean的对象。

当通过方式二获取Bean对象时,配置文件中不能出现两个不同id值,但class值相同的bean元素。否则会报错。

示例:

(二)ClassPathXmlApplicationContext对象的常用Api。

1.常用API

2.示例:

(三)Bean对象的作用范围

1.概念:

所谓Bean对象的作用范围即作用域,即c|c++的作用域是不同的两个概念。

这里的Bean作用域用于指定创建Bean的创建方式。

2.指定作用范围:

方法:

通过xml配置方式:在bean元素中添加scope属性。

示例:

scope属性的值:

singleton:单实例,默认值。

特点:

Spring容器只为该类创建一个对象,并将该对象存在Bean池中,每次获取都获取的是同一个对象。

该类实例的创建到销毁的全过程由Spring框架管理。

prototype:多实例。

特点: 

Spring容器可以为该类创建多个对象中,每次获取时都会重新创建对象。

Spring容器只负责该类的创建,不负责销毁,销毁由JVM的垃圾回收机制负责。

3.作用域的选择:

使用频次维度考虑:

使用频率高的,且没有线程安全的bean:建议使用单例。

原因:始终只有一个实例:可以减少创建时间及获取时间,同时,可以减少内存压力。

使用频次低的,且存在线程安全风险的bean:建议使用多例。

原因:单例Bean总是伴随框架开始而开始,框架结束而结束,占用内存而多例Bean 则不会。

(四)Bean对象的生命周期

1.生命周期概念:

指一个对象何时创建、何时销毁以及创建之后到销毁之前所处的状态。

2.单例Bean对象的生命周期:

创建:当Spring容器对象创建时,此类对象就会被创建。

内存驻留时间:只要容器没有销毁,bean对象就不会销毁。

销毁时机:当Spring容器销毁时,bean对象也会跟前销毁。

3.多例Bean对象的生命周期:

创建时机:当通过IoC对象获取Bean对象时,才会创建Bean对象。​​​​​​​

内存驻留时间:只要对象是在使用过程中,则就会一直驻留内存。​​​​​​​

销毁时机:当对象长时间不使用,且没有别的对象引用时,则Java垃圾回收机制就会对该对象析构。

4.总结:

单例Bean对象:由Spring全程管理此类对象(即创建、初始化、存储、销毁)。​​​​​​​

多例Bean对象:只由Spring负责创建和初始化。不负责存储和销毁(由JVM的CG机制负责)。

5.生命周期方法

初始化方法:

作用:bean对象创建后执行额外的特定的初始化操作,如帮助对象请求各类资源

执行时机:构造函数创建对象后立即执行。

创建方法:使用注解@PostConstruct描述被指定为初始化方法的方法。

示例:

@PostConstruct
public void  initObjectPool()
{
    System.out.println("initObjectPool()被调用了");
}

适用对象:单例|多例Bean对象。

析构方法:

作用:用于指定销毁Bean对象前额外操作,如释放资源等。

执行时机:Bean对象销毁前。

创建方法:使用注解@PreDestroy描述被指定为析构方法的方法。

示例:

@PreDestroy
public void preDestroyObjectPool()
{
    System.out.println("preDestroyObjectPool()被调用了");
}

适用对象:单例Bean对象。

(六)Spring的DI(依赖注入)

1.依赖注入概念:

2.依赖注入方式:

set方法注入:

概念:通过Bean对象的Set方法实现依赖注入。

配置文件方式:修改Bean装配配置文件。

方法:

构造方法注入:

概念:通过Bean对象的构造函数方法实现依赖注入。

配置文件方式:修改Bean装配配置文件。

方法:

三、Spring全注解开发

(一)自定义开发

1.开发步骤

第一步:定义Spring的配置类用于取代bean装配的配置xml文件。

第二步:获取IoC容器对象

​​​​​​​

第三步:通过IoC容器的API获取所需Bean对象。

可以通过Bean对象所有底层Bean池中的名字,也可以通过Pojo的字节码对象获取

两中方式使用方式和存在的问题与xml方式获取对象时一致。

2.常用注解

@Configuration:

作用:告诉Spring框架当前类是一个Java配置类。

说明:

该注解用于描述类。

此时描述类的具体作用:

所描述类相当于spring的bean.xml(类的装配配置文件)。

通过该类可以获取Spring的IoC容器。

@Bean

作用:将当前方法的返回值作用bean装配到spring容器中。

说明:该注解用于描述方法。所描述的方法与装配的xml文件中的bean元素类似,区别在于:方法中的存入bean池中的对象是new的,而bean元素描述的类的对象是通过框架创建的。

参数name:可选。用于指定bean池中该对象的名字,类似于bean标签中的id属性。

当省略参数时,装配bean到IoC容器中的对象的名字即为@Bean所描述的方法的方法名。

当参数存在时,则对象名即为name的值。

3.使用时机:

如果需要装配第三方技术中的bean时,只能通过自定义开发方式,装配bean对象。

(二)使用Spring扫描装配开发

1.开发步骤

第一步:使用@Component注解描述需要自动装配到IoC容器中的对象所属的Bean。​​​​​​​

第二步:使用@ComponentSan注解描述配置类(即使用@Configuration所描述的类)指定扫描的包路径。​​​​​​​

第三步:获取IoC容器对象。​​​​​​​

第四步:通过IoC对象API获取装配的Bean对象。​​​​​​​

示例:

2.常用注解

@Component:

作用:标记所描述的类需要作为bean装配到Spring的IoC容器中。

说明:

参数:

value:可选参数:用于指定存放在Bean池中的名字。

省略时:名字为该注解所描述的类的类名且首字母小写。(默认情况)

存在时:名字为value的值,其中value=可以省略。

@ComponentScan:

作用:定义以何中策略扫描装配Bean

说明:

参数:

value:可选参数:用于指定扫描策略。

省略时:默认扫描当前类所在的包及其子包。

存在时:仅扫描value的值所指定的包,其中value=可以省略。

3.使用时机:

如果需要装配开发者自定义类的对象时,使用Spring扫描的方式装配Bean。

(三)使用注解指定Bean对象的作用域和加载时机

@Scope

作用:用于指定所描述类的对象的作用域。该注解为可选的,无此注解,Spring默认指定当前类的对象的作用域为单实例的。​​​​​​​

说明:

参数:

value:可选参数,用于指定该类对象的作用域。

省略或当value值为:singleton时:默认为单例。

示例:@Scope("singleton")|@Scope|@Scope(value="singleton")

当value值为:prototype时:指定所描述类的对象为多例。

示例:@Scope("prototype")|@Scope(value="prototype");

@Lazy

作用:指定所描述的类的加载时机,默认为未延迟加载(即不使用该注解时)。​​​​​​​

说明:

参数:

value:可选参数,用于指定Bean对象是否延迟加载。默认值为true。

当为true时,延迟加载。

示例:@Lazy|@Lazy(true)|@Lazy(value=true);

当为false时,不延迟加载。

示例:@Lazy(false)|@Lazy(value=true);

加载时机:

当指定延迟加载时,则会在获取Bean对象时创建。

未指定延迟加载时,则会IoC容器对象创建时就会加载。

前置条件:

该注解只对单例Bean起作用,对多例Bean不起作用。

原因:多例Bean本身即为获取时创建。

使用时机:

针对大型的且使用时机较晚,又需要Spring框架予以装配的单例Bean对象可以使用延迟加载。

(四)使用注解为装配类注入依赖(DI注入)

注解依赖注入规则:

当一个类的属性需要Spring注入依赖的必须条件

该属性所在类必须由Spring管理

该属性必须使用特定注解描述,如:@Vaulue,@Autowired

示例:

@value

作用:使用该注解的实参为所描述的属性赋值。

说明:

该注解用于描述类的属性。

参数:

value:必需参数且无默认值。值为属性赋的值。

示例:

前置条件:

该注解只能为基本数据类型及对应的包装类型和String类的属性赋值。

该注解描述的属性的所属的类必须使用@Component及同等作用的注解描述(@Controller、@Service、@RestController、@Mapper等)

@Autowired

作用:使用该注解为描述的属性赋值。

说明:

该注解描述是类的属性,该属性为自定义类类型。此时将通过暴力反射完成赋值

可以描述类的构造函数。此时,将通过构造方法完成赋值。

可以描述类的某一属性的set就去。此时,将通过set方法完成赋值。

参数:无

前置条件:

该注解只能为开发者自定义类或接口实现类的对象注入依赖。

该注解描述的属性的所属的类必须使用@Component及同等作用的注解描述(@Controller、@Service、@RestController、@Mapper等)

@Autowired依赖注入机制:

首先,会依据类型进入依赖注入,

其次,当IOC容器中该类型的对象有多个时,@Autowired将依据对象名进入依赖注入。

@Autowired注解使用细节(即匹配规则)

前置条件:该属性描述的是接口。

匹配规则:

第一种情况:Bean池中有一个或没有该接口的实现类对象时。

该注解会匹配该接口类型的实现类。

如果没有该接口的实现类,则会报异常如下所示:

如果有该接口的实现类,且只有一个,就会使用该实现类的对象注入@Autowired描述的对象。如下所示:​​​​​​​

第二种情况:当Bean中有多个同一接口的实现类时。

该注解首先匹配属性类型,发现Bean池中有多个实现类时,会继续将Bean池中的对象名与属性名进行匹配;

如果未匹配到,则报如下异常:

org.springframework.beans.factory.NoUniqueBeanDefinitionException

如果匹配到,则使用匹配到的Bean对象实现DI注入。如下所示:

http://www.lryc.cn/news/475746.html

相关文章:

  • 深入理解C++ Lambda表达式:语法、用法与原理及其包装器的使用
  • C# 编程语言:跨时代的革命
  • 恋爱脑学Rust之Box与RC的对比
  • Rust 力扣 - 1423. 可获得的最大点数
  • Android15音频进阶之Cuttlefish搭建音频开发环境(九十二)
  • 发现不为人知的AI宝藏:发现AI新天地! —— 《第八期》
  • 基于物联网设计的地下煤矿安全监测与预警
  • Java 23 的12 个新特性!!
  • .NET 8 中 Entity Framework Core 的使用
  • ai数字人分身123口播克隆数字人小程序源码_博纳软云
  • 从0开始学PHP面向对象内容之(类,对象,构造/析构函数)
  • openGauss数据库-头歌实验1-5 修改数据库
  • 《JVM第3课》运行时数据区
  • 阅读笔记 Contemporary strategy analysis Chapter 14
  • 2024网鼎杯青龙组wp:Crypto2
  • 能通过Ping命令访问CentOS 9 Stream,但在使用Xshell连接
  • Oracle 第19章:高级查询技术
  • Excel:vba运行时错误“7“:内存溢出错误
  • 【MyBatis源码】BoundSql分析
  • KTHREAD--InitialStack和KernelStack和TSS的esp0
  • Skia基础运用(Ubuntu环境下使用BUILD.gn)
  • Vue中props和data的优先级哪个更高?
  • springboot2.x使用SSE方式代理或者转发其他流式接口
  • consul入门教程
  • 软考:大数据架构设计
  • token无感刷新+处理并发的后端方案
  • 【系统设计】让 Java “动起来”:动态语言与静态语言的比较及 DSL 实现
  • TCP Analysis Flags 之 TCP Keep-Alive
  • mfc140u.dll丢失怎么办? mfc140u.dll文件缺失的修复技巧
  • Spring Security使用