1 spring的概述
1.1 spring是什么
-轻量级开源框架,以 IOC(反转控制)和 AOP(面向切面编程)为内核
1.2 Spring的发展历程
2002年10月,Rod Johnson撰写了一本名为《Expert One-on-One J2EE设计和开发》的书。本书由Wrox出版,概括了当时Java企业应用程序开发的现状,指出了Java EE和EJB组件框架中的一些主要缺陷。在这本书中,他提出了一个基于普通Java类和注入依赖的更简单的解决方案。
在本书发布后不久,开发者Juergen Hoeller和Yann Caroff说服Rod Johnson基于书上的代码创建一个开源基础框架的项目。 于是在2003年2月左右由Rod,Juergen和Yann一起创建了一个项目,并且Yann为新框架起了一个很诗意的名字"Spring"。寓意着要给处于"冬天"的传统J2EE带来新开始。
1.3 spring 的优势
- 方便解耦,简化开发
- AOP 编程的支持
- 声明式事务的支持
- 方便程序的测试
- 方便集成各种优秀框架
- 降低 JavaEE API 的使用难度
- Java 源码是经典学习范例
spring 的体系结构
- Data Access/Integration
- Web
- Core Container
- Test
- Aop
2 IOC的概念和作用
2.1 什么是程序的耦合
耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多, 其耦合性越强, 同时表明其独立性越差 ( 降低耦合性, 可以提高其独立性)。
2.2 解决程序耦合的思路
-
工厂模式解耦
工厂模式是典型的解耦框架,高层模块只需要知道产品的抽象类,其他的实现类都不需要关心,符合迪米特法则,符合依赖倒置原则,符合里氏替换原则。 -
控制反转-Inversion Of Cont
控制反转(英语:Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。
2.3 IOC的概念与原理
-
概念
控制反转:把创建对象的过程交给spring进行管理
目的:降低耦合 -
底层原理
- Xml解析
- 工厂模式
- 反射
2.4 IOC接口
-
IOC容器的两种实现
BeanFactory 和 ApplicationContext 的区别
BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。
BeanFactory 和 ApplicationContext 的区别: 创建对象的时 间点不一样。
ApplicationContext:只要一读取配置 文件,默认情况下就会创建对象。
BeanFactory:什么使用什么时候创建对象。-
BeanFactory
-
ApplicationContext
-
ClassPathXmlApplicationContext
- 从类的根路径下加载
-
FileSystemXmlApplicationContex
- 磁盘路径上加载
-
AnnotationConfigApplicationContext
- 使用注解配置容器对象时,它用来读取注解
-
-
2.5 IOC操作bean管理
-
Spring创建对象
-
基于xml
-
1,在spring配置文件中添加bean标签
-
2,bean标签中的常用属性
-
id:给对象在容器中提供一个唯一标识。
-
class:指定类的全限定类名。
-
scope:指定对象的作用范围。
- singleton :默认值,单例的
- prototype :多例的
-
init-method:指定类中的初始化方法名称。
-
destroy-method:指定类中销毁方法名称。
-
-
3,创建时默认使用无参构造
-
4,bean 的作用范围和生命周期
单例对象:scope=“singleton”
一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:
对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
多例对象:scope=“prototype”
每次访问对象时,都会重新创建对象实例。
生命周期:
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。- 生命周期五步走
- 配置bean的后置处理器后,七步
-
5,XML的自动装配
-
引入外部属性配置文件配置数据库连接池
-
创建外部属性文件properties
-
把外部属性文件引入到Spring配置中
- 引入外部属性文件:context标签
- 配置连接池:${}
-
-
-
基于注解
-
步骤
-
第一步:引入依赖jar包:spring-aop
-
第二步:开启组解扫描
1,如果扫描多个包,多个包使用逗号隔开
2,扫描包上层目录-
context标签内的user-default-filters属性表示是否使用默认的filters
- include—filters:设置扫描那些内容
- exclude-filter: 设置哪些内容不进行扫描
-
-
第三步:创建类在类上加注解
- 类中的注解的value值可以不写,默认为首字母小写
- 类可以不用写set方法
-
-
常用注解
- @Component 通用
- @Repository:一般用于持久层(dao)的注解。
- @Service:一般用于业务层(service)的注解。
- @Controller:一般用于控制层(controller)的注解。
-
-
-
Spring注入属性
-
基于xml
-
1,set注入
-
property属性
- index:指定参数在构造函数参数列表的索引位置
- type:指定参数在构造函数中的数据类型
- name:指定参数在构造函数中的名称 用这个找给谁赋值
- value:它能赋的值是基本数据类型和 String 类型
- ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
-
-
2,有参数构造
-
constructor-arg属性
- name
- value
-
-
3,p空间注入:本质还是调用 set 方法
-
1,添加一个P名称在配置文件中
xmlns:p="http://www.springframework.org/schema/p"
-
2,P:属性
-
-
4,集合注入
它用的也是set方法注入的方式,只不过变量的数据类型都是集合
<!-- 注入 list 集合数据 --> <property name="mySet"> <list> <value>AAA</value> <value>BBB</value> <value>CCC</value> </list> </property> <!-- 注入 properties 数据 --> <property name="myMap"> <props> <prop key="testA">aaa</prop> <prop key="testB">bbb</prop> </props> </property> <!-- 注入 Map 数据 --> <property name="myProps"> <map> <entry key="testA" value="aaa"></entry> <entry key="testB"> <value>bbb</value> </entry> </map> </property>
-
数组
-
array
- value
-
-
List集合
-
list
- value
-
-
Set集合
-
set
- value
-
-
Map集合
-
map
- entry
-
-
properties 数据
-
props
- prop
-
-
在集合中注入对象
<property name="list2"> <list> <ref bean="s1"/> <ref bean="s2"/> <ref bean="s3"/> </list> </property>
-
把集合注入部分提取出来
- 1,在spring中配置文件中引入名称空间util
- 使用util标签完成提取
-
-
5,依赖注入(对象注入)
- name属性:类里面属性名称
- ref属性:创建userDao对象bean标签id值
-
6,注入空值和特殊符号
-
空值
-
特殊符号
-
1,把<>转义,<,>
-
2,把带特殊符号的内容写到CTATA中
<![CDATA[ 内容 ]]
-
-
-
7,内部bean
- 在bean里面注入对象属性时即可以使用内部bean也可以使用外部bean(如上的依赖注入)
-
8,级联赋值
- 要先生成对象属性的get方法
- 对象.对象
-
-
基于注解
-
注入属性常用的注解
- @Autowired : 自动按照类型注入
- @Qualifier:自动按照类型注入的基础之上,再按照 Bean 的 id 注入。必须和 @Autowire 一起使用
- @Resource :直接按照 Bean 的 id 注入(默认类型,加了name属性后按照名称找)
- @Value : 注入基本数据类型和 String 类型数据的属性
-
其他注解
- @Scope :指定 bean 的作用范围
- @PostConstruct :用于指定初始化方法。
- @PreDestroy: 用于指定销毁方法。
-
-
2.6 完全注解开发
-
创建一个配置类代替xml文件:用@Configuration
-
常用注解
-
@Configuration
- 作用: 用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。
- 属性: value:用于指定配置类的字节码
-
@ComponentScan
- 作用: 用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的: 是一样的。
- 属性: basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
-
@Bean
- 作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
- 属性: name:给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
-
@PropertySource
- 作用:用于加载.properties 文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到 properties 配置文件中,就可以使用此注解指定 properties 配置文件的位置。
- 属性: value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
-
@Import
- 作用: 用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问 题。 属性: value[]:用于指定其他配置类的字节码。
-
-
编写测试类
- 通过配置文件加载容器:获取容器时需要使用
AnnotationApplicationContext(有@Configuration 注解的类.class)。
- 通过配置文件加载容器:获取容器时需要使用
3 AOP 的相关概念[理解]
3.1 AOP的概念:面向切面编程
面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计、剖面导向程序设计),是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进行进一步分离,以提高程序代码的模块化程度。
通过在现有代码基础上增加额外的通知(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块进行统一管理与装饰,比如说:“对所有方法名以set*开头的方法添加后台日志”。该思想使得开发人员能够将与代码核心业务逻辑关系不那么密切的功能(如日志功能)添加至程序中,同时又不降低业务代码的可读性。面向切面的程序设计思想也是面向切面软件开发的基础。
3.2 AOP底层原理:动态代理
3.3 动态代理常有的两种方法
-
基于接口的动态代理
- 提供者:JDK 官方的 Proxy 类。
- 要求:被代理类最少实现一个接口。
-
基于子类的动态代理
- 提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar。
- 要求:被代理类不能用 final 修饰的类(最终类)。
3.4 AOP术语
-
Joinpoint(连接点)
连接点是在应用执行中能够插入切面的一个点。即程序执行过程中能够应用通知的所有点。 -
Pointcut(切入点)
切点是真正需要插入切面的一个或多个连接点。即通知被应用的具体位置(在哪些连接点)。通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点(比如Aspect切点表达式)。有些AOP框架允许我们创建动态的切点,可以根据运行时的决策(比如方法的参数值)来决定是否应用通知。 -
Advice(通知/增强)
切面的工作被称为通知。即包含了需要用于多个应用对象的横切行为。通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题。它应该应用在某个方法被调用之前?之后?之前和之后都调用?还是只在方法抛出异常时调用?
-
Introduction(引入)
引入指的是向现有的类添加新方法或属性。 -
Weaving(织入)
织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:- 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。Aspect的织入编译器就是以-这种方式织入切面的。
- 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader) ,它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入(load-time weaving, LTW)就支持以这种方式织入切面。
- 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时, AOP容器会为目标对象动态地创建一个代理对象(动态代理)。Spring AOP就是以这种方式织入切面的。
3.5 AOP的操作(准备)
-
1,Spring框架一般基于AspectJ实现AOP操作
-
2,基于AspectJ的两种方式实现
-
基于注解
-
1,创建类,在类里定义方法
-
2,创建增强类(编写增强方法)
-
3,进行注通知配置
-
开启注解扫描
-
使用注解创建类,和增强类对象
-
增强类上添加@Aspect
-
在spring配置中生成代理对象
-
开启生成代理对象: aop:aspectj-autoproxy</aop:aspectj-autoproxy>
-
在增强类中配通知注解
-
@Before
-
@AfterReturning
-
@After
-
@AfterThrowing
-
@Around环绕通知
-
参数:ProceedingJoinPoint
- 方法proceed
-
-
-
-
-
aop中的一些细节
-
相同切入点的抽取
- @Pointcut
-
有多个增强类多同一个方法增强,设置增强类的优先级
- 在增强类上添加注解@Orde(数字值类型),数字越小,优先级越高
-
-
-
基于xml
-
-
3,在项目中引入相关依赖
-
4,切入点表达式
- execution([权限修饰符] [返回类型][类全路径] 方法名称 ).
4 JDBCTemplate
4.1 概念概述
Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作
4.2 准备工作
-
1,导入依赖
- mysql连接依赖
- Spring—jdbc依赖
- spring-orm:整合其他框架
- spring-tx:关于事务的
-
2,配置数据库连接池
<!--引入资源文件--> <context:property-placeholder location="db.properties"/> <!--配置数据连接池--> <bean id="database" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean>
-
3,配置JDBCTemplate对象,注入spring
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="database"/> </bean>
-
4,创建Service,Dao相关的类注入JDBCTemplate对象
4.3 操作数据库
-
添加
-
update方法
- 有两个参数。
- 第一个参数: sgl语句
- 第二个参数:可变参数,设置sgl语句值。
-
-
修改
- update方法
-
删除
- update方法
-
查询
-
查询返回某个值
-
queryForObject()
- 第一个参数: sgl.语句。
- 第二个参数:返回类型Class.
-
-
查询返回对象
-
queryForObject()
-
第一个参数: sgl.语句。
-
第二个参数: RowMappe:RowMapper…是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装。
- new BeanPropertyRowMapper (Book. class)
-
第三个参数: sgl 语句值。
-
-
-
查询返回集合
-
query()
- 参数和上面的类似
-
-
-
数据库批量操作
-
批量添加:batchUpdate()
- 第一个参数: sgl 语句。
- 第二个参数: List 集合,添加多条记录数据。
-
批量修改:batchUpdate()
-
批量删除:batchUpdate()
-
4.4 事务操作
-
概念
-
什么是事务
-
事务四大特性(ACID)
- 原子性
- 一致性
- 隔离性
- 持久性
-
-
操作环境搭建
- dao层
- service层
- web层(Controller)
-
Spring事务管理(一般写在service层)
-
Spring管理事务用到的API
-
PlatformTransactionManager事务管理器接口
- DataSourceTransactionManager实现类
-
-
底层使用AOP原理
-
两种方式
-
编程式事务管理:自己在业务逻辑层写事务的提交,回滚的方法
-
声明事务式
-
基于注解
-
1,在spring配置文件中配置事务管理器
-
2,在spring配置文件中开启事务注解
-
引入名字空间tx
-
创建事务管理的bean,并导入数据源属性
-
开启事务注解
q
-
-
3,在service类或方法中添加一个事务的注解
-
@Transaction
- (1) @Transactional, 这个注解添加到类上面,也可以添加方法上面。
- (2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务。
- (3)如果把这个注解添加方法上面,为这个方法添加事务。
-
事务管理中的参数配置
-
propagation:事务传播行为(七种)
-
ioslation:事务隔离级别
-
三种
- 脏读
- 不可重复度
- 虚读
-
设置隔离级别四种
- 读未提交
- 读已提交
- 可重复读(默认)
- 串行化
-
-
timeout:超时时间
- 设置事务在一定时间内提交,未提交自动回滚,默认-1.已秒为单位
-
readOnly:是否只读
- readOnly,默认值false,表示可以查询,可以添加修改删除操作。
- 设置readOnly值是true,设置成true之后,只能查询。
-
rollbackFor:回滚
- 出现那些异常回滚
-
norollbackFor:回滚
- 出现那些异常不回滚
-
-
-
-
基于xml
-
1,在Spring配置文件中进行配置
- 配置事务管理器
- 配置通知
- 配置切入点,切面
-
2,配置通知
-
子主题 3
-
-
完全注解
- @EnableTransactionManagement:开启事务
- 创建数据库连接池
- 创建JDBCTemplate对象
- 创建事务管理器
-
-
-
5 Spring 5新功能
整合日志框架
spring5 的整个代码都是基于 java8 的,自身作了不少的优化,比如许多不建议使用的类和方法已经在代码库中删除。
此外,spring5 框架自带了通用的日志封装,但是我们依然可以整合其他的日志框架使用,比如 Log4j。不过在 spring5 中移除了 Log4jConfigListener,需要使用 Log4j2。
整合junit
- junit4
import org.junit.Test;
...
// junit4测试
@RunWith(SpringJUnit4ClassRunner.class)//指定测试框架
@ContextConfiguration("classpath:application.xml")//加载配置文件
- junit5
import org.junit.jupiter.api.Test;
...
// junit5测试
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:application.xml")
// 或者
@SpringJUnitConfig(locations = "classpath:application.xml")