spring 复习整理一

故事的开头

spring 复习整理一(仗剑走天涯)

小科普

DTD

DTD(Document Type Definition)即文档类型定义,是一种XML约束模式语言,是XML文件的验证机制

1
2
3
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

DTD声明始终以!DOCTYPE开头,空一格后跟着文档根元素的名称。

根元素名:configuration。所以每一个标签库定义文件都是以taglib为根元素的,否则就不会验证通过。

PUBLIC “-//mybatis.org//DTD Config 3.0//EN,这是一个公共DTD的名称(私有的使用SYSTEM表示)。这个东西命名是有些讲究的。首先它是以”-“开头的,表示这个DTD不是一个标准组织制定的。(如果是ISO标准化组织批准的,以“ISO”开头)。接着就是双斜杠“//”,跟着的是DTD所有者的名字,很明显这个DTD是MyBatis公司定的。接着又是双斜杠“//”,然后跟着的是DTD描述的文档类型,可以看出这份DTD描述的是DTD Config 3.0的格式。再跟着的就是“//”和ISO 639语言标识符。

绿色的字”http://mybatis.org/dtd/mybatis-3-config.dtd",表示这个DTD的位置

XSD

文档结构描述XML Schema Definition 缩写,这种文件同样可以用来定义我们xml文件的结构

1
2
3
4
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd
">

第一行的xmlns代表了一个xml文件中的一个命名空间,通常是一个唯一的字符串,一般使用一个url

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance" 冒号后面的为命名

xmlns:xsi 定义了一个命名空间前缀 xsi 对应的唯一字符串 http://www.w3.org/2001/XMLSchema-instance。但这个 xmlns:xsi 在不同的 xml 文档中似乎都会出现。 这是因为, xsi 已经成为了一个业界默认的用于 XSD((XML Schema Definition) 文件的命名空间。 而 XSD 文件(也常常称为 Schema 文件)是用来定义 xml 文档结构的。剩余两行的目的在于为我们的命名空间指定对应的xsd文件

Why spring?

更快、更容易、更安全

spring特性

Core technologies: dependency injection, events, resources, i18n, validation, data binding, type conversion, SpEL, AOP.

核心技术:包括依赖注入、事件模型、资源处理、国际化、数据绑定和验证、类型转化、spring表达式、面向切面编程。核心技术是一切的关键,后边衍生的多个特性都是依托于核心技术。

Testing: mock objects, TestContext framework, Spring MVC Test, WebTestClient.

Data Access: transactions, DAO support, JDBC, ORM, Marshalling XML.

Spring MVC and Spring WebFlux web frameworks.

Integration: remoting, JMS, JCA, JMX, email, tasks, scheduling, cache.

Languages: Kotlin, Groovy, dynamic languages

IOC容器

可以管理对象的生命周期、对象与对象之间的依赖关系

POJO

简单java对象

POJO的含义

没有继承任何类、也没有实现任何接口,更没有被其它框架侵入的java对象。不允许有业务方法,也不能携带connection之类的方法,实际就是普通JavaBeans

javaBean

JavaBean是一种JAVA语言写成的可重用组件。JavaBean符合一定规范编写的Java类,不是一种技术,而是一种规范

javaBean的约定

  • 所有属性为private。

  • 这个类必须有一个公共的缺省构造函数。即是提供无参数的构造器。

  • 这个类的属性使用getter和setter来访问,其他方法遵从标准命名规范。

  • 这个类应是可序列化的。实现serializable接口

POJO和javaBean的区别

POJO JAVABean
除了Java语言强加的限制外,它没有其他特殊限制 这是一个特殊的POJO,它有一些限制
它没有对成员提供太多控制 它提供对成员的完全控制
它可以实现Serializable接口 它应该实现可序列化的接口
可以通过字段名称访问字段 字段只能由getter和setter访问
字段可以具有任何可见性 字段只有私人可见性
可能/可能没有no-arg构造函数 它必须具有无参数构造函数
当您不想限制成员并让用户完全访问您的实体时使用它 当您要向用户提供您的实体,但仅向实体的一部分提供服务时,将使用它

POJO类和Bean均用于定义Java对象,以提高其可读性和可重用性。POJO没有其他限制,而bean是具有某些限制的特殊POJO

SpringBean

SpringBean是受Spring管理的对象,所有能受Spring容器管理的对象都可以成为SpringBean。Spring中的bean,是通过配置文件、javaconfig等的设置,由Spring自动实例化,用完后自动销毁的对象

SpringBean和JavaBean的区别

  • 用处不同:传统javabean更多地作为值传递参数,而spring中的bean用处几乎无处不在,任何组件都可以被称为bean。

  • 写法不同:传统javabean作为值对象,要求每个属性都提供getter和setter方法;但spring中的bean只需为接受设值注入的属性提供setter方法。

  • 生命周期不同:传统javabean作为值对象传递,不接受任何容器管理其生命周期;spring中的bean有spring管理其生命周期行为。

Entity Bean

Entity Bean是域模型对象,用于实现O/R映射,负责将数据库中的表记录映射为内存中的Entity对象,事实上,创建一个Entity Bean对象相当于新建一条记录,删除一个 Entity Bean会同时从数据库中删除对应记录,修改一个Entity Bean时,容器会自动将Entity Bean的状态和数据库同步

举个例子

加入有个user对象 它与数据库字段一一对应 那么这个user对象就是一个Entity Bean 也是一个POJO 还是一个javaBean 你要是再把它放到Spring中 那么它还是一个SpringBean

spring的两个主要接口

依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--        spring核心-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.18.RELEASE</version>
</dependency>

<!-- springIOC(依赖注入)相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.18.RELEASE</version>
</dependency>

<!-- spring上下文 Spring提供在基础IoC功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.18.RELEASE</version>
</dependency>

BeanFactory

1
public interface BeanFactory {}

提供了一种高级的配置机制,能够管理任何类型的对象。 ApplicationContext是BeanFactory的子接口

ApplicationContext

1
public interface ApplicationContext extends EnvironmentCapableListableBeanFactoryHierarchicalBeanFactoryMessageSourceApplicationEventPublisherResourcePatternResolver {}

BeanFactory提供了容器的基本功能,而ApplicationContext添加了更多特定于企业的功能

  • 更容易与Spring的AOP特性集成

  • 消息资源处理(用于国际化) 解析消息的能力 支持国际化 继承自MessageSource接口

  • 事件发布 向注册侦听器发布事件的能力 继承自ApplicationEventPublisher接口

  • 应用程序层特定的上下文,如WebApplicationContext用于web应用程序

  • 以通用方式加载文件资源的能力 继承自org.springframe .core.io.ResourceLoader接口

元数据

传统上以简单而直观的XML格式提供 要告诉Spring容器如何去【实例化、配置和组装】应用程序中的对象

基本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="userDao" name="userDao"
class="com.dream.xiaobo.dao.UserDao" factory-method="create">

</bean>

<bean id="userService" name="userService"
class="com.dream.xiaobo.service.UserService" factory-bean="userDao">

</bean>
<!-- more bean definitions go here -->

</beans>

Bean概述

Spring IoC容器管理一个或多个bean。 这些bean是使用您提供给容器的配置元数据创建的

Bean的命名

每个bean都有【一个或多个】标识符。 这些标识符在承载bean的容器(ioc容器)中必须是唯一的。 bean通常只有一个标识符。 但是,如果需要多个,则可以考虑使用别名

id属性允许您指定一个id

name属性可以多个 用逗号空格分开

Bean别名

1
<alias name="userDao" alias="userDao2"/>

实例化Bean

beanDifination本质上是描述了一个bean是如何被创建的。 当被请求时,容器会查看指定bean的定义,并使用由该beanDifination封装的配置元数据来创建(或获取)实际对象

使用构造函数实例化

1
2
3
4
<bean id="userDao" name="userDao"
class="com.dream.xiaobo.dao.UserDao">

</bean>

使用静态工厂实例化

在使用【静态工厂方法】创建的bean时,使用【class】属性指定包含【一个静态工厂方法】的类,并使用名为【factory-method】的属性指定工厂方法本身的名称

1
2
3
4
<bean id="userDao" name="userDao"
class="com.dream.xiaobo.dao.UserDao" factory-method="create">

</bean>

使用实例工厂实例化

该方法类似于通过(静态工厂方法)实例化所需的bean,容器同样可以使用【实例工厂方法】调用【非静态方法】创建一个新的bean。 要使用这种机制,请将【class】属性保留为空,并在【factory-bean】属性中指定当前容器中包含要调用的实例方法的bean的名称。 使用“factory-method”属性设置工厂方法本身的名称

1
2
3
4
5
6
7
8
9
<bean id="userDao" name="userDao"
class="com.dream.xiaobo.dao.UserDao" factory-method="create">

</bean>

<bean id="userService" name="userService"
class="com.dream.xiaobo.service.UserService" factory-bean="userDao">

</bean>

依赖注入(Dependency Injection)

依赖注入(DI)是一个【过程】在此过程中,对象仅通过【构造函数参数】、【工厂方法参数】等来确定它们的依赖项。 然后容器在创建bean时注入这些依赖项。 从根本上说,这个过程与bean本身相反(因此得名”控制反转”)

大大实现了解耦

举个例子

就好比对象A依赖于B 但是B依赖于C 正常的话就是 在B类先new一个C 然后在A类new一个B然后将放入A的有参构造中 顺序是c–>b–>a 但是spring容器不知道先后依赖顺序 他是a依赖于b 就在容器中找b创建 然后b依赖c 就在容器中找c 顺序是 a–>b–>c 这也就是另一种称呼的来源 控制反转 就像反转了一样

DI的主要两种方式

基于构造函数的依赖注入

通过容器调用带有许多参数的构造器来实现的

1
2
3
4
5
6
7
<bean name="userDao" class="com.dream.xiaobo.dao.UserDao"/>

<bean name="addressDao" class="com.dream.xiaobo.dao.AddressDao"/>
<bean name="userService" class="com.dream.xiaobo.service.UserService">
<constructor-arg index="0" ref="userDao"/>
<constructor-arg index="1" ref="addressDao"/>
</bean>

基于setter的注入

通过容器在【调用无参数构造函数】或【无参数“静态”工厂方法】实例化bean后调用bean上的setter方法来实现的

1
2
3
4
5
6
7
8
9
<bean name="userDao" class="com.dream.xiaobo.dao.UserDao"/>

<bean name="addressDao" class="com.dream.xiaobo.dao.AddressDao"/>
<bean name="userService" class="com.dream.xiaobo.service.UserService">

<property name="userDao" ref="userDao"/>
<property name="addressDao" ref="addressDao"/>

</bean>

直接值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<bean name="user" class="com.dream.xiaobo.entity.User">
<property name="id" value="1" />
<property name="name" value="xiaobo" />
<property name="like">
<array>
<value>code</value>
<value>music</value>
</array>
</property>
<property name="friends">
<list>
<value>胖子</value>
<value></value>
</list>
</property>
<property name="family">
<map>
<entry key="father" value="wanghongbo"/>
<entry key="mother" value="guofengrong"/>
</map>
</property>
</bean>

null值和空字符串

  • 空字符串
1
2
3
<bean class="ExampleBean">
<property name="email" value=""/>
</bean>
  • null
1
2
3
4
5
<bean class="ExampleBean">
<property name="email">
<null/>
</property>
</bean>

延迟初始化的 Bean

延迟初始化的bean告诉IoC容器在【第一次请求】时创建bean实例,而不是在启动时

在XML中,这种行为是由 元素上的【lazy-init】属性控制的

1
<bean name="userDao" class="com.dream.xiaobo.dao.UserDao" lazy-init="true"/>

当一个【延迟初始化的bean】是一个没有延迟初始化的单例bean的依赖时,ApplicationContext会在启动时创建这个延迟初始化的bean,因为它必须满足单例bean的依赖, 延迟初始化的bean会被注入到没有延迟初始化的其他单例bean中

自动装配

当使用基于xml的配置元数据时,您可以使用元素的【autowire】属性为beanDifination指定自动装配模式

自动装配的四种模式

运行方式 解释
no (默认)没有自动装配。 Bean引用必须由【ref】元素定义。 对于较大的部署,不建议更改默认设置,因为【明确指定协作者】可以提供更大的控制和清晰度。 在某种程度上,它记录了系统的结构
byName 通过属性名自动装配。 Spring寻找与需要自动连接的属性同名的bean。 例如,如果一个beanDifination被设置为按名称自动装配,并且它包含一个“master”属性(也就是说,它有一个“setMaster(..)”方法),Spring会寻找一个名为“master”的beanDifination并使用它来设置属性
byType 如果容器中恰好有一个属性类型的bean,则允许自动连接属性。 如果存在多个,则抛出异常,这表明您不能对该bean使用’ byType ‘自动装配。 如果没有匹配的bean,则不会发生任何事情(没有设置属性)
constructor 类似于’ byType ‘,但适用于构造函数参数。 如果容器中没有一个构造函数参数类型的bean,则会引发致命错误

自动装配的优点

自动装配可以显著减少指定属性或构造函数参数的需要

自动装配可以随着对象的发展更新配置

从自动装配中排除Bean

在每个bean的基础上,您可以将一个bean排除在自动装配之外。 在Spring的XML格式中,将元素的【autowire-candidate】属性设置为’ false ‘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class User {

private Integer id;

private String name;

private String[] like;

private List<String> friends;

private Map<String,String> family;

private AddressDao addressDao;

private List<AddressDao> addressDaoList;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<bean class="com.dream.xiaobo.dao.AddressDao" name="addressDao" />

<bean class="com.dream.xiaobo.entity.User" name="user" autowire="byType">
<property name="id" value="1" />
<property name="name" value="xiaobo" />
<property name="like">
<array>
<value>code</value>
<value>music</value>
</array>
</property>
<property name="friends">
<list>
<value>胖子</value>
<value></value>
</list>
</property>
<property name="family">
<map>
<entry key="father" value="wanghongbo"/>
<entry key="mother" value="guofengrong"/>
</map>
</property>
</bean>

循环依赖

循环依赖

流程

创建A时发现成员变量依赖B 首先去一级缓存中查找 如果有直接填充 没有 再去二级缓存中去查找 二级缓存中有 填充 没有 在去容器中查找 容器中如果有 直接进行填充 如果没有创建B 然后B同理A

你知道的越多 你不知道的越多 嘿 我是小博 带你一起看我目之所及的世界……

-------------本文结束 感谢您的阅读-------------

本文标题:spring 复习整理一

文章作者:小博

发布时间:2022年04月20日 - 19:28

最后更新:2022年04月20日 - 20:23

原始链接:https://codexiaobo.github.io/posts/2522155561/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。