第一部分

Spring体系结构 

         Spring笔记-LMLPHP

  1. core container
    1. beans与core 它们提供spring框架最基本功能,包含ioc与di
    2. context 上下文对象,基于beans与cores
    3. spel它是sprng提供的一个表达式语言
  2. Data access/integration
    1. 数据访问
    2. 集成
  3. Web
    1. Spring本身提供spring mvc
    2. 也可以与其它的web层进行集成
  4. AOP

AOP大部分情况下是使用动态代理来实现的。

     5.Test

使用spring可以方便的进行测试

 

Spring框架优点

  1. 方便解耦,简化开发

Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理

  1. AOP编程的支持

Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能

  1. 声明式事务的支持

只需要通过配置就可以完成对事务的管理,而无需手动编程

  1. 方便程序的测试

Spring对Junit4支持,可以通过注解方便的测试Spring程序

  1. 方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持

  1. 降低JavaEE API的使用难度

Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

 

IOC与DI

Spring的jar包下载

Spring的官网:spring.io

我们课程中讲解使用的是spring4.2.4

在spring3.0.2版本后,不在提供依赖jar包

docs 存在API和规范文档

libs 开发jar包

schema 开发过程中需要的xml的schema约束

spring开发环境搭建

在spring开发中,我们要根据不同的情况来导入不同的jar包,当前我们要讲解的是关于ioc与di

对于ioc与di讲解我们只需要使用spring的核心功能。

  1. beans相关
  2. core相关
  3. context相关
  4. spel相关

我们使用spring框架也会使用到配置文件,我们需要在src下创建一个关于spring的配置文件,一般情况名称叫applicationContext.xml

问题:applicationContext.xml约束?

        

         它的路径:

spring-framework-4.2.4.RELEASE-dist\spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html

 

IOC快速入门

Ioc它是什么,解决什么问题,它的原理是如何实现。

IOC  inversion of Controller 控制反转。

在程序中所说的IOC其实简单说,就是原来由我们自己实例化的对象交给spring容器来实始化。这时对象的实始化的权利就会反转。

 

程序运行时报错

原因:当前环境需要一个commons-loggin的jar包

 

总结spring使用步骤:

  1. 在applicationContext.xml文件中配置bean

  1. 创建一个AppliCationContext对象

ApplicationContext它是BeanFactory的一个子接口,我们在使用时使用的是AppliCationContext的实现类ClassPathXmlApplicationContext

 

可以通过getBean(配置文件中id名称)来获取指定的对象。

 

DI

         DI:dependency injection 依赖注入

                   在spring框架负责创建Bean对象时,动态将依赖对象注入到Bean组件。

        

 

简单说,这时UserServiceImpl中的info属性值就是ITCAST

 

面试题:IOC和DI区别?

         IOC 控制反转,是指对象实例化权利由spring容器来管理,本质是通过xml配置文件+反射+factory来实现的

         DI 依赖注入 在spring创建对象的过程中,对象所依赖的属性通过配置注入对象中。

 

Bean获取与实例化

ApplicationContext与BeanFactory关系

ApplicationContext它是扩展BeanFactory接口。

BeanFactory它采取延迟加载的方案,只有真正在getBean时才会实例化Bean

 

在开发中我们一般使用的是ApplicationContext,真正使用的是其实现类,

FileSystemXmlAppliCationContext 根据文件路径获取

ClassPathXmlApplicationContext  根据类路径获取

AppliCationContext它会在配置文件加载时,就会初始化Bean,并且ApplicationContext它提供不同的应用层的Context实现。例如在web开发中可以使用WebApplicationContext.

 

Bean的实例化方式

无参数构造

对于这种方式,注意Bean类中必须提供无参数构造。

 

静态工厂方法

需要创建一个工厂类,在工厂类中提供一个static返回bean对象的方法就可以。

实例工厂方法

需要创建一个工厂类,在工厂类中提供一个非static的创建bean对象的方法,在配置文件中需要将工厂配置,还需要配置bean

 

Bean的作用域

在bean声明时它有一个scope属性,它是用于描述bean的作用域。

可取值有:

         singleton:单例 代表在spring ioc容器中只有一个Bean实例 (默认的scope)

         prototype多例 每一次从spring容器中获取时,都会返回一个新的实例

         request 用在web开发中,将bean对象request.setAttribute()存储到request域中

         session 用在web开发中,将bean对象session.setAttribute()存储到session域中

 

在开发中常用的值是singleton与prototype

 

Bean的生命周期

Spring笔记-LMLPHP

  1. instantiate bean对象实例化
  2. populate properties 封装属性
  3. 如果Bean实现BeanNameAware执行setBeanName
  4. 如果Bean实现BeanFactoryAwar或ApplicationContextAwar设置工厂setBeanFactory或上下文对象setApplicationContext
  5. 如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization
  6. 如果Bean实现InitializingBean执行afterPropertiesSet
  7. 调用自定义的init-method方法
  8. 如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
  9. 执行业务处理
  10. 如果Bean实现DisposableBean执行destroy
  11. 调用自定义的destroy-method

 

对于bean的生命周期方法:

第三步与第四步是让Bean了解spring容器。

 

第五步与第八步 可以针对指定的Bean进行功能增强,这时一般会使用动态代理.

 

第六步与第十步:通过实现指定的接口来完成init与destroy操作

但是在开发中一般不使用第6步与第10步,原因是我们可以使用第7步与第11步来完成。

第7步与第11步的初始化与销毁操作它无耦合,推荐使用的。但是必须在配置文件中指定初始化与销毁的方法

 

总结:

         对于bean的生命周期,我们需要关注的主要有两个方法:

  1. 增强bean的功能可以使用后处理Bean, BeanPostProcessor
  2. 如果需要初始化或销毁操作我们可以使用init-method  destroy-method

 

注意:destroy-method只对scope=singleton有效果。

 

Bean的属性注入

在spring中bean的属性注入有两种

构造器注入

Setter方法注入

关于ref属性作用

使用ref来引入另一个bean对象,完成bean之间注入

 

集合属性的注入

在spring中对于集合属性,可以使用专门的标签来完成注入例如:list   set  map properties等集合元素来完成集合属性注入.

List属性注入

如果属性是数组类型也可以使用list完成注入

Set属性注入

 

Map属性注入

 

Properties属性注入

Java.util.Properties是java.utilsMap的实现类,它的key与value都是String类型.

 

名称空间p和c的使用

Spring2.0以后提供了xml命名空间。

P名称空间

C名称空间

首先它们不是真正的名称空间,是虚拟的。它是嵌入到spring内核中的。

使用p名称空间可以解决我们setter注入时<property>简化

使用c名称空间可以解决我们构造器注入时<constructor-arg>简化

 

使用setter注入

在applicationContext.xml文件中添加p名称空间简化setter注入

 

使用c名称空间来解决构造器注入

在applicationContext.xml文件中添加c名称空间

 

 

注:如果c或p名称空间操作的属性后缀是”-ref”代表要引入另一个已经存在的bean,例如

SpEl

spring expression language  是在spring3.0以后的版本提供

它类似于ognl或el表达式,它可以提供在程序运行时构造复杂表达式来完成对象属性存储及方法调用等。

Spel表达式的格式  #{表达式}

 

示例1:完成bean之间的注入

示例2 支持属性调用及方法调用 

 

Spring注解开发

在spring中使用注解,我们必须在applicationContext.xml文件中添加一个标签

<context:annotation-config/>作用是让spring中常用的一些注解生效。

要使用contex名称空间,必须在applicationContext.xml文件中引入

完成bean注册操作

@Component

 

测试时报错

原因:如果你使用的是spring3.x那么不会出现这个错误,如果使用的是spring4.x会报错,原因是缺少jar包。

导入jar后运行还有错误

我们在applicationContext.xml文件中使用了一个标签      <context:annotation-config />,它代表的是可以使用spring的注解,但是我们在类上添加的注解,spring不知道位置。

要解决这个问题,我们可以使用<context:component-sacn base-package=””>

 

 

在spring2.5后为@Component添加了三个衍生的注解

@Repository 用于DAO层

@Service 用于service层

@Controller  用于表现层

对于我们的bean所处在的位置可以选择上述三个注解来应用,如果你的bean不明确位置,就可以使用@Component.

 

属性依赖注入

  1. 简单的属性注入

 

  1. 复杂的属性注入

 

注意:如果要扫描多个包下的注解可以写成以下:

 

注意:@Value @Autowired它们可以修饰属性,也可以修饰setter方法,如果写在属性上,就不需要提供setter方法。

 

 

@Autowired它默认是根据类型进行注入。

 

如果与@Qualifier一起使用,就可以根据名称来进行注入。

我们也可以使用下面的方式来根据名称进行属性注入

 

其它注解

@Scope它以描述bean的作用域。

 

它相当于init-method=”myInit

它相当于是destroy-method=”myDestroy”

注意:对于销毁的方法它只对bean的scope=singleton有效。

 

Spring在web开发中的应用

1.,在web项目中要使用spring需要导入一个jar包

 

2.在web.xml文件中配置Listener

        

这个ContextLoaderListener它实现了ServletContextListener

在这个listener中,当服务器启动时,将ApplicationContext对象,其实是它的一个实现类

WebApplicationContext,对象存入到了ServletContext中。

 

 

3.我们还需要在web.xml文件中配置applicationContext.xml文件的位置

         默认情况下会在WEB-INF目录 下查找applicationContext.xmls

         如果applicationContext.xml文件不是在默认位置,我们可以在web.xml文件中配置

        

Classpath:applicationContext.xml 它代表的是在当前工程的类路径下(可以理解成是在src)下来查找applicationContext.xml文件。

contextConfigLocation它是在listener中声明的一个常量,描述的就是spring配置文件的位置。

 

Spring整合junit4测试

Spring整合junit4可以方便我们的测试。

 

  1. 需要导入一个spring-test.jar包

 

  1. 可以在测试类上如下操作

 

第二部分

Spring AOP

AOP概述

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP是一个概念,并没有设定具体语言的实现,它能克服那些只有单继承特性语言的缺点,spring2.0之后整合AspectJ第三方AOP技术。

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。

 

主要功能

日志记录,性能统计,安全控制,事务处理,异常处理等等

主要意图

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

 

AOP与OOP区别

OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。

而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。

         换而言之,OOD/OOP面向名词领域,AOP面向动词领域。

 

AOP相关术语

目标对象target

指的是需要被增强的对象,由于spring aop是通过代理模式实现,从而这个对象永远是被代理对象。

连接点(join point)

所谓连接点是指那些被拦截到的点,在spring中这些点指的是方法,因为spring只支持方法类型的连接点

切入点(pointcut)

表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方

简单说切入点是指我们要对哪些连接点进行拦截的定义

 

通知(advice)

所谓通知是指拦截到连接点之后所要做的事情就是通知,通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

Advice 定义了在 pointcut 里面定义的程序点具体要做的操作

引介introduction

引介是一种特殊的通知,在不修改类代码的前提下,introduction可以在运行期为类动态地添加一些方法或属性

切面aspect

是切入点和通知的结合

织入weaving

织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期,类装载期,运行期进行。

Spring采用动态织入,而aspectj采用静态织入

代理Proxy

一个类被AOP织入增强后,就产生一个结果代理类

图解

AOP底层实现

AOP分为静态AOP和动态AOP。静态AOP是指AspectJ实现的AOP,他是将切面代码直接编译到Java类文件中。动态AOP是指将切面代码进行动态织入实现的AOP。Spring的AOP为动态AOP,实现的技术为: JDK提供的动态代理技术 和 CGLIB(动态字节码增强技术) 

JDK动态代理

在运行 ,在JVM内部动态生成class字节码对象(Class对象)

Jdk动态代理只针对于接口操作

第一个参数:目标类的类加载器对象

第二个参数:目标类的实现接口的Class[]

第三个参数:InvocationHandler它是一个接口,它的作用是是代理实例的调用处理程序 实现的接口,接口中定义了一个方法

 

目标Target

代理工厂

CGLIB动态代理

CGLIB(Code Generation Library)是一个开源项目

是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类

如果你要单独使用CGLIB,那么需要导入cglib的jar包还需要一个asm相关jar包,但是spring框架的spring-core.jar包中已经集成了cglib与asm

注意:jdk的动态代理只可以为接口去完成操作,而cglib它可以为没有实现接口的类去做代理,也可以为实现接口的类去做代理。

 

Cglib动态代理

setCallback传递的参数是Callback类型,我们使用的是MethodInterceptor

 

注意:cglib它可以为没有实现接口的类做代理,也可以为接口类做代理.

 

问题:spring采用的是哪一种动态机制:

         如果目标对象,有接口,优先使用jdk动态代理

         如果目标对象,无接口,使用cglib动态代理。

 

Spring AOP编程

Spring的传统aop编程

讲解的目的是为了更好的理解aop。

在传统的spring aop开发中它支持增强(advice)有五种:

  1. 前置通知  目标方法执行前增强  org.springframework.aop.MethodBeforeAdvice
  2. 后置通知  目标方法执行后增强 org.springframework.aop.AfterReturningAdvice
  3. 环绕通知  目标方法执行前后进行增强  org.aopalliance.intercept.MethodInterceptor
  4. 异常抛出通知 目标方法抛出异常后的增强 org.springframework.aop.ThrowsAdvice
  5. 引介通知 在目标类中添加一些新的方法或属性(不讲解)

org.springframework.aop.IntroductionInterceptor

 

经典的基于代理的AOP开发(了解)

基本的jar包

  1. bean
  2. core
  3. context
  4. expression
  5. aop
  6. 需要aop联盟的依赖jar包

第一步:编写目标(target)

第二步增强(advice)

 

第三步在applicationContext.xml文件中配置

第四 测试

 

基于aspectJ切点传统开发

第一步:在spring的配置文件中定义目标与通知

第二步:使用<aop:xxx>标签来完成切面与切点声明

注意1:需要在xml配置文件中导入aop声明

注意2:因为我们使用aspectj的切面声明方式 需要在导入aspectj的jar包

传统spring aop开发总结

第一步:编写目标对象(target)

 

第二步:编写通知(advice)

传统的aop开发中,通知是需要实现指定接口。

 

第三步 在配置文件中配置切面(切面=切点+通知)

<aop:config>来声明要对aop进行配置

<aop:pointcut>它是用于声明切点(简单说就是对哪些方法进行拦截)

<aop:advisor> 定义传统的aop的切面,传统的aop切面它只能包含一个切点与一个增强

<aop:aspect>定义aspectj框架的切面.,它可以包含多个切点与多个通知

 

关于切点表达式写法

这个语法源于aspectJ的语法,spring中aop开发,对aspectj不是完全支持,只支持部分语法。

 

在开发中使用的比较多的是execution语法.

关于execution语法常用:

  1. execution(public * *()) 所有的public的方法
  2. execution(* cn.itheima.aop.*(..)) 所有的aop包下的所有类的方法(不包含子包)
  3. execution(* cn.itheima.aop..*(..)) 所有的aop包及其子包下的所有类的方法
  4. execution(* cn.itheima.aop.IOrderService.*(..)) IOrderService接口中定义的所有方法
  5. execution(* cn.itheima.aop.IOrderService+.*(..)) 匹配实现特定接口所有类的方法
  6. execution(* save*(..)) 匹配所有的以save开头的方法

Spring整合aspectj框架实现的aop

在现在的开发中使用这种方案比较多.

在spring2.0以后它支持jdk1.5注解,而整合aspectj后可以使用aspectj语法,可以简化开发。

 

Aspect:切面 =切点+通知(多个切点与多个通知的组合)

AspectJ 它是一个第三方框架,spring从2.0后可以使用aspectJ框架的部分语法.

 

AspectJ框架它定义的通知类型有6种

  1. 前置通知Before 相当于BeforeAdvice
  2. 后置通知AfterReturning 相当于AfterReturningAdvice
  3. 环绕通知 Around 相当于MethodInterceptor
  4. 抛出通知AfterThrowing 相当于ThrowAdvice
  5. 引介通知DeclareParents 相当于IntroductionInterceptor
  6. 最终通知After 不管是否异常,该通知都会执行

相比spring 的传统AOP Advice多了一个最终通知

基于xml配置方案

第一步:创建目标(target)

第二步:创建通知(增强  advice)

注意:在aspectj中它的增强可以不实现任何接口,只需要定义出增强功能(方法)

 

第三步:在spring的xml 配置文件中来配置

<aop:config>下的<aop:aspect>是aspectJ框架用来声明切面的。

前置通知

后置通知

环绕通知

异常抛出

注意:目标行为只有抛出了异常后才会执行这个增强方法

 

最终通知

无论是否有异常,最终通知都会执行.

关于通知上的参数

  1. 在前置通知上可以添加JoinPoint参数

通过它可以获取目标相关的信息

使用前置通知可以完成日志记录,权限控制

 

  1. 在后置通知上添加的参数

第二个参数val它可以获取目标方法的返回值

注意:需要在配置文件中配置

 

  1. 环绕通知上的参数

它是我们开发中应用最多的,可以完成日志操作,权限操作,性能监控,事务管理

  1. 抛出异常通知上的参数

第二个参数Throwable它是用于接收抛出的异常

注意:需要在配置文件中声明

  1. 最终通知上的参数

可以使用最终通知完成资源释放
 

关于代理方式选择

在spring的aop开发中,它使用的是代理方案,代理实现有两种:

  1. jdk的proxy
  2. cglib

spring框架默认情况下,会对有接口的类使用proxy代理(jdk动态代理)。没有接口的类使用cglib代理

Proxy-target-class的值默认是false,它代表有接口使用proxy代理

问题:如果现在对目标要使用cglib代理(不考虑是否有接口)?

只需要将proxy-target-class设置为true.

 

基于annotation方案

 第一步:编写目标

 

在spring的配置文件中配置扫描注解

 

第二步:编写增强(advice)

使用@Aspect来声明切面

使用@Before来声明前置通知

注意:必须在spring的配置文件中开启aspectJ注解自动代理功能。

第三步:测试

其它通知类型及参数

后置通知

 

环绕通知

 

异常抛出通知

 

最终通知

 

使用@Pointcut注解定义切点

在每一个通知中定义切点,工作量大,不方便维护,我们可以使用@Pointcut来声明切点

 

切点允许逻辑运算例如mypointcut()||mypointcut1

 

关于代理方式选择

Proxy-target-class默认值是false,代表的是如果目标是有接口的使用proxy代理,如果没有接口使用cglib.

如果将proxy-target-class=true,不管目标是否有接口,都会使用cglib进行代理。

第三部分

Spring jdbc Template

Spring提供了一个jdbc模板,它类似于dbutils工具。

 

问题:如何使用spring jdbc template?

第一:要导入相关的jar包

        

         在这个基础上我们还需要导入

        

        

         还需要导入相关的数据库驱动jar包。

第二:spring jdbc template快速入门

快速入门

第一步:导入相关jar包,创建了一个JdbcTemplateTest1测试类

第二步:创建库与表

CREATE DATABASE springtest;

 

USE springtest;

 

CREATE TABLE t_user(

        

         id INT PRIMARY KEY AUTO_INCREMENT,

         NAME VARCHAR(20),

         age INT,

         sex VARCHAR(20)

)

 

INSERT INTO t_user VALUES(NULL,'tom',20,'男');

INSERT INTO t_user VALUES(NULL,'fox',30,'男');

INSERT INTO t_user VALUES(NULL,'tony',40,'男');

 

SELECT * FROM t_user;

 

第三步:编码

 

配置spring内置的连接池DriverManagerDataSource

创建一个连接池

创建一个jdbcTemplate完成操作

测试代码

 

C3P0开源连接池配置

  1. 导入c3p0相关的jar包

 

  1. 创建一个ComboPoolDataSource对象,设置相关的属性

 

引入外部属性文件

Spring支持将经常修改属性,在properties文件中声明,在xml配置文件中引入外部的properties文件的信息。

在applicationContext.xml文件中引入

在自己配置中需要从properties文件中引入的信息可以使用${name}方式来获取

JdbcTemplate CRUD

执行insert update delete操作

只需要使用JdbcTemplate的update方法就可以执行insert update delete操作

 

执行select操作

简单数据返回

 

 

复杂数据返回

注意:如果只返回一个domain对象,可以使用queryForObject方法,如果返回的是List<?>对象,可以使用query方法,但是都需要使用RowMapper来对ResultSet进行处理。

RowMapper它有一个实现类叫BeanPropertyRowMapper
如果使用BeanPropertyRowmapper,实体类必须提供一个无参数的public构造方法,类中的bean属性名称与表中的列要对应
注意:这个类是在spring2.5后提供。

 

Spring 事务管理

案例—转账操作

创建一个关于帐户表

CREATE TABLE account(

         id INT PRIMARY KEY AUTO_INCREMENT,

         NAME VARCHAR(20),

         money DOUBLE

)

 

INSERT INTO account VALUES(NULL,'tom',1000);

INSERT INTO account VALUES(NULL,'fox',1000);

创建service与dao

对于数据的操作使用spring jdbc template

 

关于service与dao的配置

我们让dao去extends JdbcDaoSupport类,这个类中它创建了JdbcTempate,前提是我们需要注入一个dataSource.

在dao中在获取JdbcTemplate可以使用父类提供的getJdbcTemplate方法来获取。

转账操作的问题

如果在转账操作过程中出现问题,那么转账会出现问题,结果如下

也就是我们程序需要事务控制。

 

Spring事务管理机制

Spring事务管理的四个优点:

  1. 提供一致的对于不同的事务管理的API
  2. 支持声明式事务管理(重点)
  3. 编程事务管理(在开发中应用比较少)
  4. 优秀的整合与Spring的数据访问

我们重点讲解spring的事务管理的相关的API,还有声明式事务管理

Spring事务管理主要提供了三个接口来完成

  1. org.springframework.transaction.PlatformTransactionManager

这是一个事务管理器,可以来选择相关的平台(jdbc  hibernate  jpa…)

  1. TransactionDefinition

它定义事务的一些相关信息 例如 隔离 传播 超时 只读

  1. TransactionStatus

它主要描述事务具体的运行状态

 

PlatformTransactionManager

平台事务管理器

在不同的持久化层解决技术它的事务代码不一样。

JDBC开发

       Connection con=……;

       con.setAutoCommit(false);//开启事务

       con.rollback();

       con.commit();

Hibernate开发

       Session session=….;

       Transaction t=session.beginTransaction();

       t.commit();

       t.rollback();

PlatformTransactionManager接口API

DataSourceTransactionManager 主要针对于JdbcTemplate开发  MyBatis开发

HibernateTransactionManasger主要针对于Hibernate开发

JpaTransactionManager 主要针对于JPA开发。

 

TransactionDefinition

它描述的是事务的定义信息。

        

在TransactionDefinition中定义了大量的常量

隔离

以下是关于隔离性相关信息

事务的四个特性 ACID  原子性 一致性 隔离性 持久性。

不考虑事务隔离性有什么问题?

         脏读,不可重复读 虚读。

ISOLATION_DEFUALT 它使用后端数据库的默认隔离级别(spring中选项)

ISOLATION_READ_UNCOMMITTED 不能解决问题,会发生脏读 不可重复读 虚读

ISOLATION_READ_COMMITTED 可以解决脏读 会产生不可重复读与虚读。

可以解决脏读,不可重复读 解决不了虚读

串行化,可以解决所有问题

对于不现的数据库,它的底层默认事务隔离级别不一样。

Oracle数据库它默认的是read_committed

Mysql数据库它默认的是repeatable_read.

 

超时

默认值是-1 它使用的是数据库默认的超时时间。

 

只读

         它的值有两个true/false,如果选择true一般是在select操作时

        

传播

它解决的是两个被事务管理的方法互相调用问题。它与数据库没关系,是程序内部维护的问题。

以下定义了事务的传播行为

以上操作中最常用的三种:

默认值 两个操作处于同一个事务,如果之前没有事务,新建一个事务

两个操作处于不同的事务


它是一种嵌套事务,它是使用SavePoint来实现的。事务回滚时可以回滚到指定的savepoint,注意:它只对DataSourceTransactionManager有作用

 

以下了解

支持当前事务,如果不存在,就不使用事务

支持当前事务,如果不存在,抛出异常

以非事务运行,如果有事务存在,挂起当前事务

以非事务运行,如果有事务存在,抛出异常

 

TransactionStatus

它定义了事务状态信息,在事务运行过程中,得到某个时间点的状态

 

声明式事务管理

事务管理方式

  1. 编码方案 不建议使用,它具有侵入性。在原有的业务代码基础上去添加事务管理代码
  2. 声明式事务控制,基于AOP对目标进行代理,添加around环绕通知。

这种方案,它不具有侵入性,不需要修改原来的业务代码

 

基于xml配置声明式事务管理方案

第一步:在applicationContext.xml文件中添加aop与tx的名称空间

第二步:在applicationContext.xml文件中配置

         Spring提供的advice是传统的spring advice

  1. 声明事务管理器

  1. 配置通知

Spring为我们提供了一个TransactionInterceptor来完成增强

对于这个增强,我们可以使用spring为我们提供的一个标签<tx:advice>来完成操作  

  1. 配置切面

因为使用的是传统的spring的advice,需要使用<aop:advisor>

基于annotation声明式事务管理方案

可以使用@Transaction来在类或方法上添加声明式事务管理

注意:需要在applicationContext.xml文件中使用

相当于开启注解事务控制

 

问题:关于xml方式与annotation方式的优缺点?

         从简单上来说,使用注解更方便。

         使用配置的方案,可以对事务配置进行集中维护。

        

第四部分

SSH框架整合

SSh=struts2+spring+hibernate 

struts2 2.3.24

spring 4.2.4

hibernate 5.0.7

关于xml配置文件的整合方式

SSH整合jar包

Struts2框架需要jar包

Asm 是关于字节码操作

Commons-fileupload 关于文件上传

Commons-io 关于io流操作工具

Commons-lang 也是一个工具,包含了关于数据与字符串操作

Freemaker 标签库模板文件

Javassist 它也是关于字节码操作,动态代理可以使用它实现(类似于cglib)

Log4j关于日志

Ognl 关于ognl表达式

Struts2-core  xwork-cor  struts2框架底层是使用xwork

 

Struts2与spring整合还需要这个包

 

如果需要使用struts2提供的json处理

 

注意:如果使用注解方案,我们还需要导入一个jar包

 

Hibernate框架需要的jar包

Antlr 语法解析包

Dom4j 解析xml

Geronimo-jta  apache geronimo它是一个开源javaEE服务器 Geronimo-jta是这个开源项目提供jar包,在hibernate中是关于jta事务相关

Hibernate-commoins-annotations

这个包是我们在hibernate下来使用jpa相关的注解,这样它不依赖于hibernate

Hibernate-core 开发hibernate必须

Hibernate-jpa 它是关于hibernate对jpa的支持

Jandex 用于索引annotation

Javassist 关于字节码操作(注意:strtus2中也引入这个jar包了)

Jboss-logging 它是关于jboss统一日志处理

 

如果使用关于jpa相关操作需要导入jpa依赖jar包

 

C3p0连接池

还需要数据库相关的驱动jar包

 

还需要静态日志处理

Spring框架需要的jar包

Spring最基本jar包

AOP开发

 

Spring jdbc

Spring  事务管理需要tx

Spring整合hibernate

Spring整合web开发

如果使用到junit测试

 

还需要commons-loggin jar包

 

创建工程完成整合前期准备

需要的配置文件:

Strtsu2框架   src/strtus.xml

Hibernate框架   src/hibernate.cfg.xml  在domain有 Xxx.hbm.xml

Spring框架   src/applicationContext.xml

关于日志   log4j.properties

关于数据库连接   db.properties

 

Spring整合hibernate

         基本原理:就是由spring来管理hibernate的SessionFactory

方式一:零障碍整合(了解)

         我们只需要使用spring中提供的一个LocalSessionFacotry来加载Hibernate的配置文件。

        

 

Ssh-xml工程加载到服务器后,如果可以自动创建表,就代表spring整合hibernate ok.

注意:我们必须配置spring的ContextLoaderListener

方式二(spring管理hibernate配置)

不在需要hibernate.cfg.xml文件,所有关于hibernate.cfg.xml文件中的配置都在spring的配置文件中来配置。

 

首先要配置数据源

接下来引入properties文件

创建LocalSessionFactoryBean来完成spring管理hibernate中的SessionFactory

上述的props可以简化成下面方案

 

加载hbm.xml配置文件

mappingResources它类似于我们之前<mapping resource=””>

mappingLocations它加载时是根据类路径加载 classpath:路径

mappingJarLocations它会加载jar文件中的hbm.xml文件

mappingDirectoryLocations 它加载的目录

 

spring整合hibernate后的DAO

spring整合hiberante后,我们的dao只需要继承HibernateDaoSupport类(注意导入的hibernate包.默认是hibernate3,要根据自己的版本选择)

在HibernateDaoSupport中只需要注入SessionFactory就可以获得到HibernateTemplate,它是对hibernate操作的一个简单封装,可以让我们方便使用原来hibernate的操作.

 

编写service及测试

 

测试

事务管理

 

HibernateTemplate API介绍

保存操作  session.save()

修改操作  session.update()

删除操作  session.delete()

类似于session.saveOrUpdate()根据持久化对象的状态来判断执行save或update

获取操作   get()  load()

 

Find操作  类似于session.createQuery().setParameter().list()

类似于hibernate中的QBC查询,完全的面向对象方案

下面这个可以执行命名查询

可以在User.hbm.xml文件中定义hql或sql

 

Spring整合struts2框架

前期准备

创建一个addUser.jsp页面

创建UserAction类

Struts.xml文件中配置

 

Spring整合struts2原理分析

  1. spring整合struts2框架必须导入一个jar包

struts2-spring-plugin.jar

 

  1. struts2框架配置文件加载顺序
  1. default.properties
  2. struts-default.xml
  3. strtus-plugin.xml
  1. 在struts2框架中所有的action interceptor  result全是bean,在struts2框架中默认是使用strtus2自己bean初化操作.

 

  1. 当我们在工程中导入struts2-spring-plugin.jar文件

就会加载这个包下的strtus-plugin.xml

这时bean的创建由spring来管理。

 

  1. 这时在创建Action时它执行的代码

上述代码,在执行时,首先会从spring容器中来获取,如果获取不到,会buildBean

 

通过上述分析,spring整合struts2框架它的方式有两种

  1. spring管理action(简单说就是在applicationContext.xml文件中来声明action)
  2. action自动装配service

 

spring整合struts2框架方式一(掌握)

这种方案是基于spring管理action

  1. 在applicationContext.xml文件中配置

 

  1. 在action类中

 

  1. 在struts.xml文件

Class的值就是bean的id值

 

注意:必须在web.xml文件中配置struts2框架的Filter

Spring整合struts2框架方式二(action中自动注入service)

Struts.xml文件中

Class还是类的全名

 

这时就会将action类中需要的注入servcie自动注入

在default.properties中有一段配置

这时就会根据名称进行autoWires

 

我们可以修改注入的方式

我们在struts.xml文件中修改了注入的方式,根据type进行注入

 

Spring整合struts2框架总结

  1. 如果在struts.xml文件中<action class=”cn.itheima.action.UserAction”>如果写的是全类名,我们使用action自动装配service方案
  2. 如果在struts.xml文件中<action class=”userAction”>这时,在applicationContext.xml文件中要配置<bean id=”userAction” class=” cn.itheima.action.UserAction”>
  3. 以上操作的前提是必须导入struts2-spring-plugin.xml文件

在这个文件中它改变struts2的bean工厂

  1. 默认情况下如果采用action自动装配service方案,这时每一次请求都会新创建一个action,并且service的装配类型是by name
  2. 如果我们采用的是spring管理action这种方案我们必须在<bean>声明中添加scope=prototype”,原因是struts2框架的action每一次请求都应该是一个新的action

关于annotation整合方式

Jar包导入

在原来的xml基础上在多导入一个jar包

只有导入这个jar包后,我们才能使用struts2框架的注解  @Namespace @Action

 

配置文件

Web.xml文件中要配置

Spring的配置文件 applicationContext.xml

Struts2的配置文件 struts.xml

 

使用JPA注解来定义PO类

@Entity 定义实体类

@Table 定义表

@Id 主键

@GeneratedValue 生成主键策略

@Column 定义列

Spring整合hibernate

Dao编写

如何在dao中得到HibernateTemplate对象,原来是在applicationContext.xml文件中通过配置方案注入了一个SessionFactory对象,UserDao的父类HibernateDaoSupport,会帮助我们根据SessionFactory来得到HibernateTemplate

 

或者以上代码可以向上抽取公共代码,以下:

 

Service编写

 

 

问题:service需要事务管理,怎样处理?

 

 

Action编写

使用@Controller  @Scope  

以上注解的作用是由spring管理action,它是一个多例的。

 

问题:如何完成struts2框架的流程?

 

基于annotation的ssh整合总结

在ssh的annotation整合时,必须要多导入的一个包

对于dao,service,action我们使用

@Repository  @Service  @Controller来完成bean注册。

在dao中我们使用以下方案将SessionFactory注入,在dao中就可以使用HibernateTemplate

在service及action中使用@Autowire来注入dao及service

一定要在applicationContext.xml文件中开启注解扫描

对于PO类我们使用JPA的注解 @Entiry @Table  @Id  @GeneratedValue  @Column

要在applicationContext.xml文件中配置SessionFactory时来确定扫描包

 

对于Struts2框架,我们需要@Namespace @Action @ParentPakcage @Result来定义struts2流程

要求action类必须是在action actions struts struts2这样的包中才会扫描struts2相关注解

 

SSH整合延迟加载问题解决

  1. 修改UserDao中的findById

  1. 添加一个user.jsp页面

 

  1. 在UserAction中处理user_findById请求

 

以上程序在执行后,报错

 

 

 

 

 

 

问题分析:

解决no session问题:

  1. 不使用延迟加载
  2. 手动将延迟加载初始化 Hibernate.initialize(延迟对象)
  3. 使用spring提供的一个OpenSessionInViewFilter来解决(web.xml文件中配置)

基本的原理就是将session的关闭操作不在service层完成,而是在web层才关闭session.

注意:openSessionInViewFilter一定要在Struts2 Filter前配置.

 

10-03 20:06