Spring

137 阅读9分钟

1. Spring Framework

Spring Framework:Spring框架,是Spring中最早最核心的技术,也是所有其他技术的基础。

系统架构图

image.png (1)核心层

  • Core Container:核心容器,这个模块是Spring最核心的模块,其他的都需要依赖该模块

(2)AOP层

  • AOP:面向切面编程,它依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强
  • Aspects:AOP是思想,Aspects是对AOP思想的具体实现

(3)数据层

  • Data Access:数据访问,Spring全家桶中有对数据访问的具体实现技术
  • Data Integration:数据集成,Spring支持整合其他的数据层解决方案,比如Mybatis
  • Transactions:事务,Spring中事务管理是Spring AOP的一个具体实现,也是后期学习的重点内容

(4)Web层

  • 这一层的内容将在SpringMVC框架具体学习

(5)Test层

  • Spring主要整合了Junit来完成单元测试和集成测试

Spring的学习主要包含四部分内容

image.png

核心概念

IOC/DI思想:使用对象时,由主动new产生对象转换为由IOC容器提供对象,此过程中对象创建控制权由程序转移到IOC容器,此思想称为控制反转IOC,Inversion of Control)。IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象。这些被创建的对象在IOC容器中统称为Bean。在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入DI,Dependency Injection)

这两个概念的最终目标就是:充分解耦,具体实现靠:

  • 使用IOC容器管理bean(IOC)
  • 在IOC容器内将有依赖关系的bean进行关系绑定(DI)
  • 最终结果为:使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系.

2. IOC相关内容

bean

  • 为什么bean默认为单例?

    • bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象
    • bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
  • bean在容器中是单例的,会不会产生线程安全问题?

    • 如果对象是有状态对象,即该对象有成员变量可以用来存储数据的,因为所有请求线程共用一个bean对象,所以会存在线程安全问题。
    • 如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的,因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题。
  • 哪些bean对象适合交给容器进行管理?

    • 表现层对象
    • 业务层对象
    • 数据层对象
    • 工具对象
  • 哪些bean对象不适合交给容器进行管理?

    • 封装实例的域对象,因为会引发线程安全问题,所以不适合。

bean的实例化过程

bean本质上就是对象,对象在new的时候会使用构造方法完成,那创建bean也是使用构造方法完成的。

  • 构造方法(常用)

  • 静态工厂(了解)

  • 实例工厂(了解)

    • FactoryBean(实用)

1. 构造方法实例化

构造函数改成private测试,发现实例化时依旧能访问到类中的私有构造方法,显而易见Spring底层用的是反射,添加一个参数再测试会报错,说明Spring底层使用的是类的无参构造方法

因为每一个类默认都会提供一个无参构造函数,所以其实真正在使用这种方式的时候,我们什么也不需要做。这也是我们以后比较常用的一种方式。

2. 静态工厂实例化(了解)

image.png

3. 实例工厂与FactoryBean

image.png Spring为了简化这种配置方式就提供了一种叫FactoryBean的方式来简化开发,这种方式在Spring去整合其他框架的时候会被用到。

image.png

bean生命周期

  • bean生命周期是什么?

    • bean对象从创建到销毁的整体过程。
  • bean生命周期控制是什么?

    • 在bean创建后到销毁前做一些事情。、

(1)关于Spring中对bean生命周期控制提供了两种方式:

  • 在配置文件中的bean标签中添加init-methoddestroy-method属性
  • 类实现InitializingBeanDisposableBean接口,这种方式了解下即可。

(2)对于bean的生命周期控制在bean的整个生命周期中所处的位置如下:

  • 初始化容器

    • 1.创建对象(内存分配)
    • 2.执行构造方法
    • 3.执行属性注入(set操作)
    • 4.执行bean初始化方法
  • 使用bean

    • 1.执行业务操作
  • 关闭/销毁容器

    • 1.执行bean销毁方法

(3)关闭容器的两种方式:

  • ConfigurableApplicationContext是ApplicationContext的子接口

    • close()方法
    • registerShutdownHook()方法

注意,ApplicationContext中没有close()和registerShutdownHook()方法,需要先将ApplicationContext更换成ClassPathXmlApplicationContext或者ConfigurableApplicationContext

```
ClassPathXmlApplicationContext ctx = new 
    ClassPathXmlApplicationContext("applicationContext.xml");
```

3. DI相关内容

依赖注入描述了在容器中建立bean与bean之间的依赖关系的过程。

Spring提供了两种注入方式,分别是:

  • setter注入

    • 简单类型<property name="" value=""/>
    • 引用类型<property name="" ref=""/>
  • 构造器注入
    在BookServiceImpl类中将bookDao的setter方法删除掉,并添加带有bookDao参数的构造方法

    • 简单类型<constructor-arg name="" index="" type="" value=""/>
    • 引用类型<constructor-arg name="" index="" type="" ref=""/>

依赖自动配置

IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配。

自动装配只需要修改applicationContext.xml配置文件即可:

(1)将<property>标签删除

(2)在<bean>标签中添加autowire属性

最后对于依赖注入,需要注意一些其他的配置特征:

  1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
  3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
  4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

集合注入

image.png
  • property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array><list><set><map><props>标签
  • List的底层也是通过数组实现的,所以<list><array>标签是可以混用
  • 集合中要添加引用类型,只需要把<value>标签改成<ref>标签,这种方式用的比较少

4. IOC/DI配置管理第三方bean和加载properties文件

举例 使用setter注入数据库连接四要素

  • driverClassName:数据库驱动
  • url:数据库连接地址
  • username:数据库连接用户名
  • password:数据库连接密码

image.png

加载properties文件

image.png

5. 核心容器总结

IOC容器中的核心容器可以把它简单的理解为ApplicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

容器相关

  • BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载

  • ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载

  • ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能

  • ApplicationContext接口常用初始化类

    • ==ClassPathXmlApplicationContext(常用)==
    • FileSystemXmlApplicationContext

bean相关

image.png

依赖注入相关

image.png

6. 注解开发

注解开发定义bean

image.png 对于@Component注解,还衍生出了其他三个注解@Controller@Service@Repository,方便我们后期在编写类的时候能很好的区分出这个类是属于表现层业务层还是数据层的类。

纯注解开发

image.png 接着读取Java配置类初始化容器对象

//加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

注解开发作用范围与生命周期管理

image.png

注解开发依赖注入DI

Spring为了使用注解简化开发,没有提供构造函数注入setter注入对应的注解,只提供了自动装配的注解实现。

  • 对于引用类型:
    @Autowired
    private BookDao bookDao;

提问: @Autowired可以写在属性上,也可以写在setter方法上,最简单的处理方式是写在属性上并将setter方法删除掉, 为什么setter方法可以删除呢?

:自动装配基于反射设计创建对象并通过暴力反射私有属性进行设值,普通反射只能获取public修饰的内容,暴力反射除了获取public修饰的内容还可以获取private修改的内容,所以此处无需提供setter方法。

  • 对于简单类型(值类型):

@Value一般会被用在从properties配置文件中读取内容进行使用,使用注解加载properties配置文件,要先在配置类上添加@PropertySource注解

@Configuration
@ComponentScan("com.itheima")
@PropertySource({"jdbc.properties","xxx.properties"})
public class SpringConfig {
}
    @Value("itheima")
    private String name;

注解开发管理第三方bean

  1. 第一步,使用独立的配置类管理第三方bean。
image.png
  1. 第二步,将独立的配置类加入到核心配置类SpringConfig,推荐使用@Import导入式。

image.png

注解开发实现为第三方bean依赖注入

在使用@Bean创建bean对象的时候,如果方法在创建的过程中需要其他资源该怎么办?

  • 简单类型
    成员变量
image.png
  • 引用类型
    方法形参

image.png

Spring整合Mybatis

Spring与Mybatis的整合,大体需要做两件事,

第一件事是:Spring要管理MyBatis中的SqlSessionFactory

第二件事是:Spring要管理Mapper接口的扫描

核心步骤:

  • 使用SqlSessionFactoryBean封装SqlSessionFactory需要的环境信息 image.png

  • 使用MapperScannerConfigurer加载Dao接口,创建代理对象保存到IOC容器中。

image.png 这个MapperScannerConfigurer对象也是MyBatis提供的专用于整合的jar包中的类,用来处理原始配置文件中的mappers相关配置,加载数据层的Mapper接口类

Spring整合Junit

image.png

上面两个配置都是固定格式,当需要测试哪个bean时,使用自动装配加载对应的对象,