Spring
一、Spring简介
1.Spring也是一款开源的框架结构,Spring框架在2004年发布的第一个版本,它的诞生是为了全面的简化Java企业级应用的开发。Spring框架的目的也是致力于全面的简化Java开发。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6i0UcKzf-1607599304135)(file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml6172\wps1.jpg)]
2.Spring框架的设计和实现,集成和采用了很多的设计模式:工厂模式、代理模式、单例模式、策略模式、观察者模式、装饰器模式等。
3.未来我们会使用Spring框架管理和集成MVC开发中各个层的框架。
二、工厂模式的践行
1.通过工厂模式可以设计完成创建一些复杂的对象, 工厂类主要就是提供对象。
2.工厂的使用流程:
2.1 初始化工厂
2.2 从工厂中获取对象
3.使用工厂模式的好处: 通将一些对象交由工厂管理和创建, 使得我们对于对象创建的管理变得更加灵活。 更利于项目的维护。
三、第一个Spring应用程序开发
1.搭建开发环境
1.1 引入依赖
1.2 引入配置文件 - 工厂配置文件
2.编码开发
2.1 编写工厂配置文件
<!--声明你要让Spring工厂管理创建的对象-->
<!--
一个bean代表让spring工厂帮我们创建一个对象
id属性值唯一,是我们从spring工厂获取对象的依据
class属性指定类的全限定名
-->
2.2 从工厂中获取对象
@Test
public void test0(){
//1.初始化工厂:需要指定工厂配置文件路径
ApplicationContext context = new ClassPathXMLApplication("applicationContext.xml");
//2.从工厂中获取对象
Person p1 = context.getBean("p1",Person.class);
System.out.println(p1);
}
PS:
- JavaSE环境下初始化Spring工厂的对象: ClassPathXmlApplicationContext
- JavaWEB环境下初始化工厂的对象: WebXmlApplicationContext
四、注入(Injection)【重点】
-
什么叫注入: Spring的注入是指Spring工厂在创建对象的同时,可以给对象依赖的属性注入值。
-
Spring提供的注入方式:set注入、构造注入、自动注入。
-
set注入的实现:
public class Person implements Serializable{
private Integer id;
private String name;
private String sex;
}
3.1给8种基本数据类型和字符串类型注入
<bean id="p1" class="com.xxx.entity.Person">
<!--
配置属性值的注入
name属性值为当前类对应属性变量名
value 是指定的值
-->
<property name="id" value="1"></property>
<property name="name" value="Jerry"></property>
<property name="sex" value="男"></property>
</bean>
3.2给list集合注入
<property name="stringList">
<lsit>
<!-- 一对value标签代表添加一个元素 -->
<value>Tom</value>
<value>Jack</value>
<value>xiaoLi</value>
</lsit>
</property>
3.3 给set集合注入
<!--set集合类型-->
<property name="stringSet">
<set>
<value>中国</value>
<value>印度</value>
<value>美国</value>
</set>
</property>
3.4 给map集合注入
<!--map集合类型-->
<property name="stringMap">
<map>
<!-- 一个entry标签代表向map集合添加一个键值对-->
<entry key="k1" value="悟空"/>
<entry key="k2" value="悟能"/>
<entry key="k3" value="悟净"/>
</map>
</property>
3.5 给Properties集合注入
<!--properties集合类型-->
<property name="properties">
<props>
<prop key="driverClassName">oracle.jdbc.OracleDriver</prop>
<prop key="url">jdbc:oracle:thin:@localhost:1521:xe</prop>
<prop key="name">Jerry</prop>
</props>
</property>
3.6 自定义对象类型属性注入
<!--创建address对象-->
<bean id="addr1" class="com.baizhi.entity.Address">
<property name="id" value="1"/>
<property naem="name" value="朝阳区"/>
</bean>
<bean id="p2" class="com.xxx.entity.Person">
<!--自定义对象类型注入-->
<property naem="address" ref="addr1"></property>
</bean>
PS: set注入的本质是通过调用对应属性的set 方法实现的值的注入, 要想使用set注入就必须给属性提供set方法 。
4.构造注入 :构造注入是指通过调用对应的有参构造方法完成属性值的注入。
4.1 根据构造方法参数变量名匹配注入
public Emp(Integer id,String name,Double salary,Integer age){
this.id = id;
this.name = name;
this.salary = salary;
this.age = age;
}
<bean id="emp" class="com.XXX.entity.Emp">
<!-- 一对constructor-arg标签,匹配一个构造方法参数-->
<constructor-arg name="id" value="2"></constructor-arg>
<constructor-arg name="name" value="Tom"></constructor-arg>
<constructor-arg name="salary" value="1000"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
</bean>
4.2 其他方式的构造注入 【了解】
public Emp(Integer id,String name,Double salary,Integer age){
this.id = id;
this.name = name;
this.salary = salary;
this.age = age;
}
<bean id="emp" class="com.XXX.entity.Emp">
<!-- 一对constructor-arg标签,匹配一个构造方法参数-->
<constructor-arg index="0" value="2"></constructor-arg>
<constructor-arg index="1" value="Tom"></constructor-arg>
<constructor-arg index="2" value="1000"></constructor-arg>
<constructor-arg index="3" value="18"></constructor-arg>
</bean>
PS: 在使用构造注入的时候, constructor-arg标签的数量必须能匹配到类里面对应个数的有参构造方法。
5.自动注入
<bean id="uid" class="com.XXX.dao.UserDaoImpl"></bean>
<!--
autowire 自动注入的属性
值为byName,代表根据类中属性变量名,到Spring工厂中匹配指定beanid的对象完成注入
值为byType,代表根基类中属性类型,到Spring工厂中匹配指定类型的对象完成注入
注意:不管是byName还是byType方式实现自动注入,都必须给属性提供set方法
-->
<--!<bean id="userService" class="com.XXX.service.UserServiceImpl" outowire="byName"></bean>-->
<bean id="userService" class="com.XXX.service.UserServiceImpl" outowire="byType"></bean>
PS: 自动注入仅限于给属性类型是自定义对象类型进行注入 。
五、IOC和DI【重点】
1.IOC(Inverse Of Control)控制反转:控制反转是指将创建对象的权利由程序员反转给Spring工厂容器管理。
2.DI(Dependency Injection)依赖注入:Spring工厂在帮助我们创建对象的同时,可以给对象依赖的属性注入值。
3.基于IOC和DI编程的好处:
3.1 使我们应用中各个对象之间进一步做到了弱耦合。
3.2 更利于项目的维护和升级。
六、Spring工厂对于创建对象次数的控制
-
Spring工厂默认以单例方式创建对象。
-
自定义设置Spring工厂创建对象的次数:
<!--
scope=singleton 代表以单例模式创建当前对象
scope=prototype 代表以多例模式创建当前对象,每当从工厂获取对象时就会创建一个新的
-->
<bean id="emp5" class="com.XXX.entity.Emp" scope="prototype"></bean>
注意: 默认 scope=singleton 单例创建对象 。
七、自定义对象的初始化方法和销毁方法
/**
*定义初始化和销毁方法
*/
public void initEmp(){
System.out.println("===init emp===");
}
public void destroyEmp(){
System.out.println("===destroy emp===");
}
<!--
scope=singleton 代表以单例模式创建当前对象
scope=prototype 代表以多例模式创建当前对象,每当从工厂获取对象时就会创建一个新的
-->
<bean id="emp5" class="com.XXX.entity.Emp" scope="singleton" init-emthod="initEmp" destroy-method="destroyEmp"></bean>
八、Spring工厂创建对象的生命周期
1、创建对象的时机:
1.1 Spring工厂初始化会创建所有的单例对象。
1.2 对于多例的对象, 在我们从工厂获取对象的时候创建。
2.销毁对象:
2.1 Spring工厂在关闭的时候会销毁所有的单例对象。
2.2对于多例的对象销毁时机由虚拟机的垃圾回收决定。
一、复杂对象的创建
- 什么样的对象属于我们说的复杂对象: 不能通过直接new出来的对象。
- FactoryBean接口的应用 - 创建复杂对象 【重点】
3.实现一个创建Connection对象的FactoryBean接口实现类
3.1 实现FactoryBean接口中的三个方法
3.2 将实现类交给Spring工厂管理
3.3从工厂获取对象
二、配置文件参数化 【掌握】
1.在Spring配置文件中引入外部的一个properties配置文件
1.1 引入spring-context模块依赖
1.2 在spring配置文件头引入新的xsd
1.3 书写引入外部小配置文件标签
1.4 在spring配置文件中使用小配置文件里的参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XauWz4WN-1607599304153)(file:///
三、静态代理 - 代理的思想 【了解】
1.由于在实际开发过程中, 在核心的业务功能之外会存在一些额外的辅助性的功能代码,这些额外的功能代码,在有些情况下是需要的,有些情况下是不需要的, 那么我们未来让这样的额外功能代码可以灵活的加入到核心业务中执行, 可以使用代理的思想,去编写代理类。
2.静态代理实现的要求
2.1 原始类和代理类实现相同的接口
2.2代理类保留原始类的对象的引用
3.代理类: 通过代理类给原始类增加额外功能。
4.静态代理的缺陷:
4.1 代理类的数量会随着原始类的增加,越来越多。
4.2 额外功能冗余。
四、AOP 【重点】
1.AOP是什么
AOP是指面向切面编程, 以切面为单位解决开发中的一些问题。
2.Spring的AOP本质 : 基于Spring的动态代理实现的一种开发模式,动态代理的代理类是在程序的运行过程中产生的(区别于静态代理的代理类是程序员手动编写出来的)。动态代理的目的也是通过代理类给原始类(目标类)增加额外功能。
3.Spring动态代理开发
3.1编写原始类
3.2编写通知(额外功能的编写)
①前置通知:在原始业务功能执行前加入额外功能。需要实现MethodBeforeAdvice
② 后置通知:在原始业务功能执行之后加入额外功能。需要实现AfterReturningAdvice
③ 环绕通知:在原始业务功能执行的前后加入额外功能。需要实现MethodInterceptor
④ 异常通知:在原始业务功能执行过程抛出异常的时候加入额外功能。需要实现ThrowsAdvice
异常通知方法实现的模板:
3.3定义切入点:目的是明确额外功能要加入的位置。 是指额外功能加入项目中的哪些包 哪些类 哪些方法上。
①execution切入点函数 【重点】
② within切入点函数 : 只关注匹配包结构 和 类名。
③ args切入点函数 : 只关注匹配方法的参数列表。
④ @annotation切入点函数 : 关注注解类型的匹配。
// 匹配方法上使用了指定类型注解的 方法加额外功能
<aop:pointcut id="pct" expression="@annotation(com.baizhi.anno.Log)"/>
⑤ 切入点函数运算符
or - 或者
// 匹配类名是OrderServiceImpl 或者ProductServiceImpl类中所有的方法加额外功能
execution(* *..OrderServiceImpl.*(..)) or execution(* *..ProductServiceImpl.*(..))
and - 并且
! - 取非
3.4编织(weave): 其实就是在组装切面。
3.5测试
4.AOP总结 【重点】
4.1 AOP称为面向切面编程,是基于Spring的动态代理实现的, 主要功能和作用就是通过代理类给原始类增加额外功能。 面向切面我们可以理解为将定义好的额外功能与指定的切入点进行组装形成的切面。
4.2 AOP编程的好处:
基于AOP的编程,我们将项目中一些横切入业务功能里的冗余的代码,提取到一处进行定义,然后基于切点进行配置,最终将额外功能应用到项目中需要的方法中, 大大的提高了:
- 代码的复用性
- 项目的可维护性
一、Spring动态代理实现原理
1.JDK动态代理实现 : 要求原始类和代理类实现同一个接口。
2.cglib动态代理实现: 要求代理类去继承原始类。
PS: Spring在生成代理类的对象时, 会根据原始类是否实现了接口,来决定采用哪种动态代理实现。如果原始类实现了接口,则采用JDK动态代理生成代理对象。 如果原始类没有实现任何接口,则采用cglib动态代理实现生成代理对象。
二、 SM整合(Spring+Mybatis)【重点】
1.整合思路 : 当Spring整合Mybatis后, Spring会接管mybatis-config.xml。
2.数据源(连接池)的使用
2.1常见的一些数据源: dbcp、c3p0、druid (阿里巴巴研发)。
2.2druid连接池的使用:
3.Spring与mybatis整合配置
4.SM整合的流程
4.1 环境搭建
①要额外的引入一个mybtais和Spring整合的中间依赖
②引入spring-core.xml
③ 引入mapper文件
PS: mybatis-config.xml不再需要引入
4.2 编码
① 建表
② 定义DAO
③ 编写mapper文件
④ 编写spring-core.xml,完成整合的相关配置
测试
三、事务控制 【重点】
1.什么事务
事务是用户操作数据库的基本单元。也可以说一个业务操作就对应到数据库的一个事务。
2.JDBC中的事务
2.1 控制事务的对象: Connection
① 手动提交: conn.commit()
② 手动回滚: conn.rollback()
2.2 JDBC默认事务提交方式: 自动提交。 没执行完一条SQL语句自动提交事务。
3.Mybatis中的事务
3.1 管理事务的对象: SqlSession(一个SqlSession中封装了一个Connection对象)
①手动提交事务: sqlSession.commit()
②手动回滚: sqlSession.rollback()
3.2 mybatis默认事务提交方式: 自动做回滚处理。
4.Spring中的事务控制
4.1 Spring框架采用声明式事务管理机制。开发人员在使用Spring开发的时候, 只需要按照Spring框架的要求在配置文件中声明管理事务的配置, 最终由 Spring框架帮助我们完成事务的管理。
4.2 事务管理对象:
DataSourceTransactionManager (需要依赖数据源dataSource)
4.3 Spring事务管理的开发流程
①创建原始类的对象 - XXXService
②编写通知 - 进行事务功能管理的配置
③定义切点
④编织
⑤测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Ihqf8gb-1607599304187)(file:///
5.事务属性
5.1 事务传播属性 : 事务传播属性是用于控制事务在方法相互调用的过程中如何加到方法上。
① PROPAGATION_REQUIRED 【默认】: 代表事务是必须的。 如果当前环境有事务,则加入当前环境的事务中运行。如果当前环境没有事务,则创建一个新的事务运行。应用于写操作。
② PROPAGATION_SUPPORTS: 代表支持事务。如果当前环境有事务,则加入当前环境的事务中运行。如果当前环境没有事务, 不会创建新的事务。 应用于查询操作。
四、Spring整合Mybatis 加上事务
4.环境搭建
1.1 引入依赖 : spring的依赖(aop依赖、事务管理依赖)、mybatis整合 spring的依赖
1.2 引入配置文件:
① spring的核心配置文件
② mapper文件
③ 日志文件
2.编码整合
2.1 建表
2.2 定义DAO
2.3 编写DAO接口实现的mapper文件
2.4 定义service接口, 书写service接口的实现
2.5 编写spring核心配置文件
① 配置数据源
② 配置SqlSessionFactory的创建
③ 配置DAO接口实现类的创建
④ 配置service的创建
⑤ 进行事务管理配置
- 配置事务管理对象的创建
2)配置事务通知额外功能
-
定义切入点
-
编织(组装)
一、事务开发
1.Spring事务开发的流程
1.1 创建原始类的对象
1.2 配置事务通知
1.3 定义切入点
1.4 编织
2.事务属性
2.1 事务传播属性
① PROPAGATION_REQUIRED【默认】: 事务是必须的。当前环境下有事务,会加入当前事务。 当前环境下没有事务,则创建新的事务。
② PROPAGATION_SUPPORTS: 支持事务。当前环境下有事务,加入当前事务。 当前环境下没有事务,不会创建新事务(此时的执行不会有事务)。
③ PROPAGATION_REQUIRES_NEW: 不管在什么环境下都会创建新的事务。 即使当前环境下有事务,也会创建新的事务;此时会先挂起当前环境的事务,然后创建一个新的事务运行。 当前环境没有事务,那么创建新的事务运行。
④ PROPAGATION_NOT_SUPPORED :不支持事务。当前环境有事务,我也不加入。当前环境没有事务,我也不创建。 总之我不会在事务的环境运行。
⑤ PROPAGATION_NEVER : 一定不能在有事务的环境运行, 当前环境有事务我就抛异常。
⑥ PROPAGATION_MANDATORY: 一定得运行在事务环境中, 当前环境没有事务我就抛异常。
⑦ PROPAGATION_NESTED : 嵌套式事务。需要JDBC3.0以上才支持,没有太大的实战价值。
2.2 隔离性 【面试点】
2.2.1名词解释:脏读:强调的是在多事务的环境下,一个事务读取到了另一个事务没有提交的数据。不可重复读: 强调的是在一个事务中针对一条数据的两次读取,结果不一致。幻影读: 强调的是在一个事务中, 针对一张表进行的两次统计结果不一致。 |
---|
2.2.2事务隔离级别① 读未提交 - read uncommitted : 一个事务可以读取到另一个事务没有提交的数据。 1) 会存在问题: 脏读、不可重复读、幻影读 2) 安全性: 最差 3) 性能: 最高② 读提交 - read committed : 一个事务只能读取到其他事务提交的数据。 1) 会存在问题: 不可重复读、幻影读 2)安全性: 稍好 3)性能: 一般③ 可重复读 - repeatable read : 可以保证一个事务中进行的多次读取结果是一致的。 当一个事务操作某一条数据的时候,那么这条数据会加行级锁, 此时其他事务不能操作这条数据。 1) 会存在问题: 幻影读 2) 安全性: 较高 3)性能:较差④ 序列化读 - serializable : 也称为串行读, 当一个事务针对一张表进行操作的时候,那么整张表会被加锁。 1)解决了上面的所有问题。 2) 安全性: 最高 3) 性能:最差 |
Oracle数据库默认隔离级别是 读提交。Mysql数据库默认隔离级别时 可重复读。 |
2.3 回滚性
2.3.1 Spring默认情况当程序抛出运行时异常自动回滚事务。 程序抛出非运行时异常,事务会提交。
2.3.2 自定义事务的回滚性【测试演示】:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S08FrsvK-1607599304188)(file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml3440\wps1.jpg)]
PS: 开发中通常就是用Spring默认的回滚性设置。
2.4 只读性 : 一旦设置了事务只读性, 如果在数据库支持的前提下,那么当前事务中只允许执行读操作,不允许执行写操作,如果执行了写操作会抛出异常。
PS: 通常开发中建议查询操作设置readonly=true,理论上会提升查询效率。
2.5 超时性 : 是指可以针对一个事务的执行时间进行设置,一旦超过这个时间则抛出异常。
PS: 采用Spring默认的即可。
3.总结开发中事务属性的设置
二、Spring+Struts2整合 【重点】
1.整合的思路
2.整合的配置
2.1 web.xml的配置
2.2 spring和struts2的配置文件
三、注解式管理事务 【重点】
1.在配置文件中开启事务注解驱动
2.在service上使用事务管理的注解
2.1 在类上使用@Transactional
2.2 在方法上使用@Transactional
2.3 如果类上使用了事务注解, 同时类里面的某个方法上也使用了事务注解,那么最终会议方法上事务注解的配置给方法加事务。 (方法上的事务注解配置优先)
四、Spring的注解开发 【重点】
1.注解式开发是约定大于配置的开发思想实现。 通过在项目中应用注解进行开发,可以大大的简化我们的配置文件,进而提高开发效率。 注解也是开发人员和框架之间的一种约定。
2.使用注解开发基本流程
2.1 在配置文件中开启注解驱动(开启注解开发的功能)
PS: base-packe属性值,支持通配符。
2.2 使用注解
2.3 测试
3.Spring中常用的注解
3.1 @Repository 注解主要用于DAO的类上。
3.2 @Service 注解主要用于service类型。
3.3 @Controller 注解主要用于action实现类上。
3.4 自动注入实现的注解:
@Autowired 用于给对象依赖的属性自动注入, 是由Spring框架提供。
9304199)]
2.3 如果类上使用了事务注解, 同时类里面的某个方法上也使用了事务注解,那么最终会议方法上事务注解的配置给方法加事务。 (方法上的事务注解配置优先)
四、Spring的注解开发 【重点】
1.注解式开发是约定大于配置的开发思想实现。 通过在项目中应用注解进行开发,可以大大的简化我们的配置文件,进而提高开发效率。 注解也是开发人员和框架之间的一种约定。
2.使用注解开发基本流程
2.1 在配置文件中开启注解驱动(开启注解开发的功能)
PS: base-packe属性值,支持通配符。
2.2 使用注解
2.3 测试
3.Spring中常用的注解
3.1 @Repository 注解主要用于DAO的类上。
3.2 @Service 注解主要用于service类型。
3.3 @Controller 注解主要用于action实现类上。
3.4 自动注入实现的注解:
@Autowired 用于给对象依赖的属性自动注入, 是由Spring框架提供。
@Resource 用于给对象依赖的属性自动注入,是由JDK原生提供的。