待解决疑问
- bean的生存周期
- 多线程bean是否存在线程争用问题
- 什么是控制反转IoC? 《IoC基础》
0. spring的核心
- 依赖注入(Dependency injection,DI)
- 面向切面编程 (aspect-oriented programming,AOP)
1. spring之旅
1.1 简化Java开发
为了降低Java开发的复杂性,Spring采用了以下四种策略:
- 基于POJO的轻量级和最小侵入性编程
- 通过依赖注入和面向接口实现松耦合
- 通过切面和惯例进行声明式编程
- 通过切面和模板减少样板式代码
1.2 容纳你的Bean
Spring的容器实现归纳为两种类型:
- bean工厂是最简单的容器,提供最基本的DI支持
- 应用上下文基于BeanFactory构建,并提供应用框架级别的服务
Spring自带多种类型的应用上下文:
- AnnotationConfigApplicationContext: 从一个或者多个基于Java的配置类中加载Spring应用上下文
- AnnotationConfigWebApplicationContext: 从一个或者多个基于Java的配置类中加载Spring web应用上下文
- ClassPathXmlApplicationContext: 从类路径下的一个或者多个Xml配置文件中加载上下文定义,把应用上下文的定义文件作为类资源
- FileSystemXmlApplicationcontext: 从文件系统下的一个或者多个Xml配置文件中加载上下文定义
- XmlWebApplicationContext: 从web应用下的一个或者Xml配置文件中加载上下文定义
1.3 俯瞰spring风景线
spring模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rkIuXJdG-1616029510615)(en-resource://database/2142:1)]
2. 装配Bean
- 声明Beasn
- 构造器注入和Setter方法注入
- 装配Bean
- 控制Bean的创建和销毁
2.1 Spring配置的可选方案
三种主要的装配机制:
- 在XML中进行显示配置
- 在Java中进行显示配置
- 隐式的bean发现机制和自动装配
尽可能地使用自动配置的机制,显示配置越少越好
2.2 自动化装配bean
如果Spring能够进行自动化装配的话,那何苦还要显示地将这些bean专配在一起呢?
spring从两个角度实现自动化装配Bean:
- 组件扫描(component scanning): spring会自动发现上下文中所创建的Bean
- 自动装配(autowiring): spring自动满足bean之间的依赖
实现自动化扫描依赖与两个注解,一个是 @Component(实现创造出Bean),另一个是 @Autowired(实现自动话装配)。
2.3 通过Java代码装配bean
有些情况下自动化配置的方案行不通,例如想要在第三方库中的组件装配到你的应用中,这是没有办法在它的类中添加@Component和@Autowired注解,因此不能使用自动化。此时必须使用显示配置:Java和XML。
通过Java代码装配Bean主要是通过注解 @Configuration,@Bean 和 new 关键字。
2.4 通过XML装配Bean
- 构造器注入有两种方案可供选择
- 使用
- 使用c-命名空间
- 设置属性
- 使用
- 使用p-命名空间
3. 高级装配
- spring profile
- 条件化的bean声明
- 自动装配与歧义性
- bean的作用域
- spring的表达式语言
3.1 环境与profile
profile就是用来实现在不同的运行场景(典型场景为生产、测试环境中可能用到不同的数据库)中可以有不同的配置,激活某一个profile,就可以使用其对应的配置,而不用每次都改配置文件。
《高级装配—配置profile bean》
3.2 条件化的bean
条件化的bean意思就是一个bean到底是否需要被创建
主要利用注解:@Conditional
3.3 处理自动装配的歧义性
歧义性是在进行自动注入的时候不止一个满足条件的bean满足条件,spring就不知道该注入哪一个bean,注入就会失败,报错NoUniqueBeanDefinitionException。
有两种方法解决:
- 用 @primary注解表名首选bean
- 用 @Qualifier限定需要自动装配的Bean
3.4 bean的作用域
在默认情况下,所有bean都是单例的,也就时不管注入多少次,都是同一个实例。
这一节就是解决我一直以来的一大疑惑,大家都用同一个实例,岂不是在某些情况下会相互影响,spring有自己的解决方案,就是作用域
bean的作用域:
- 单例: 整个应用中就一个,可以理解为一个全局的
- 原型: 每次获取都get到一个全新的 使用注解 @scope(“prototype”)
- 会话: 在web应用中,为每次会话创建一个bean实例
- 请求: 在web应用中,为每个请求创建一个bean实例
3.5 运行时值注入
运行时 的含义就是将一些值的处理推迟到运行时,它可以理解为硬编码的反义词,这样带来的好处是这些值要想改变不用通过程序重新编译。
- 使用注解 PropertySource和 Environment
也就是PropertySource指明一个配置文件,Environment可以去配置文件中获取属性值 - 使用Spring表达式语言进行装配
SpEL表达式形如 #{…},可以实现运算、获取bean属性值、获取系统属性值、正则表达匹配、集合操纵等多种功能,最终获得一个String类型的值。
4.面向切面的Spring
- 面向切面编程的基本原理
- 通过POJO创建界面
- 使用@AspectJ注解
- 为AspectJ切面注入依赖
4.1 什么是面向切面编程
- 通知
- 连接点
- 切点
- 切面
- 引入
- 织入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-acCXvvDj-1616029510618)(en-resource://database/2929:1)]
4.1.2 Spring对AOP的支持
Spring支持四种类型的AOP:
- 基于代理的经典Spring AOP
- 纯POJO切面
- @AspectJ注解驱动的切面
- 注入式AspectJ切面(适用于Spring各版本)
4.2 通过切点来选择连接点
4.3 使用注解创建切面
10.通过Spring和JDBC征服数据库
- 定义Spring对数据访问的支持
- 配置数据库资源
- 使用Spring的JDBC模板
10.1 Spring的数据访问哲学
将持久层隐藏在接口之后
10.1.1 了解Spring的数据访问异常体系
JDBC的SQLExeception不得不捕获,但捕获了又没什么用(无法从中恢复),并且SQLExeception是一个通用的异常类型,没有丰富异常的体系。Spring的数据库异常全部继承自DataAccessException,这是一个非检查型异常,所以不用必须去捕获。
10.1.2 数据访问模块化
10.2配置数据源
10.2.1 使用JNDI
《JNNDI是什么?》
10.2.2 使用数据源连接池
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qcrS0LLk-1616029510620)(en-resource://database/2931:2)]
10.2.3 基于JDBC驱动的数据源
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lOdfNnAT-1616029510624)(en-resource://database/2933:1)]
没有连接池的功能,不建议使用
10.2.4 使用嵌入式的数据源
10.2.5 使用profile选择数据源
10.3 在spring中使用JDBC
10.3.1 应对失控的JDBC代码
失控主要指大量的JDBC样板代码,如创建链接、异常处理等
10.3.2 使用JDBC模板
Spring的JDBC框架承担了资源管理和异常处理的工作,从而简化JDBC代码。这里主要关注JdbcTemplate。
在Spring中配置JdbcTemplate:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49XvCkRS-1616029510626)(en-resource://database/2935:2)]
@Repository的作用:注解的作用不只是将类识别为Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。
11.使用对象-关系映射持久化数据
- 使用Spring和Hibernate
- 借助上下文Session,编写不依赖于Spring的Repository
- 借助Spring使用JPA
- 借助Spring Data实现自动化的JPA Repository