1.程序的耦合
概述:也就是程序之间的依赖关系。调用者和被调用者的依赖关系。
遇到“程序耦合”的情况:
(1)jdbc的注册驱动。
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
我们在开发中遵循的原则:编译时不依赖,运行时依赖。
解决依赖关系:使用反射创建类对象。
Class.forName(“com.mysql.jdbc.Driver”);
使用反射创建类对象引发的新问题:类对象名固定了,换数据库时,需要修改源码。
解决的办法:使用配置文件,通过读取配置文件来反射创建类对象。
(2)CRM客户联系人案例
表现层,业务层相关联。都是一层一层new出来的。
类路径:
普通工程:src下
Web工程: WEB-INF/classes
解决的方法:使用工厂类来创建类对象。
加载properties文件方法:
1、使用类加载器。(三步骤)
(1)Properties props=new Properties();
(2)InputStream in=类名.class.getClassLoader().getResourceAsStream(“文件名”);
properties文件必须放在类路径下。
可以将文件放在src或者某个包下。
InputStream in=new FileInputStream(“src/文件名”);
(3)props.load(in);
2、ResourceBundle类。
这个类只能用于读取properties文件,别的文件读不了。
这个类只能用于读取,不能写。
这个类只能读取类路径下的文件,其它路径的读取不了。
方法参数是按照包名.文件名(不带后缀)来写的。
可以将文件放在src或者某个包下。
ResourceBundle bundle=ResourceBundle.getBundle(“文件名,不带后缀”);
代码实现:SpringReady项目
2.线程安全问题的分析
类成员变量有线程安全问题,方法成员变量没有。
因为:方法独立进栈。
有线程安全问题,有类成员变量,必须是多例的。例如:Action
没有线程安全问题的前提下,单例对象更好。
只有方法成员时,单例和多例对象都没有线程安全问题。
3.Spring概述
分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(反转控制)和AOP(面向切面编程)为内核。
4.Spring的IOC
概念:控制权发生改变,IOC即控制反转。
作用:用于解决程序间的耦合问题。即解耦
IOC是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的spring框架的核心。控制反转一般分为两种类型:1、依赖注入(应用广泛) 2、依赖查找
5.Spring的体系结构
Spring的IOC(XML版)
6.搭建XML版的IOC开发环境
(1)导入jar包
(2)在src创建bean.xml文件
导入schema约束:
7.Spring的入门案例
ClassPathXmlApplicationContext 只能加载类路径下的配置文件
FileSystemXmlApplicationContext 可以加载磁盘任意位置的配置文件
1、获取容器
ApplicationContext ac=new ClassPathXmlApplicationContext(“bean.xml”);
2、根据bean的id获取类对象
类名 变量名=(类名)ac.getBean(“”);
需求: 通过bean配置文件,创建相应的类对象。
代码实现:Spring1项目 IOCXML.Demo01
8.Bean的两种创建规则
BeanFactory :
提供的是一种延迟加载思想来创建bean对象。Bean对象什时候用什么时候创建。
实现类:
XmlBeanFactory(Resource resource);
步骤:
1、获取容器
Resource resource=new ClassPathResource(“bean.xml”);
BeanFactory factory=new XmlBeanFactory(resource);
2、根据bean的id获取类对象
类名 变量名=(类名)factory.getBean(“”);
ApplicationContext :
提供的是一种立即加载思想来创建bean对象,只要解析完配置文件,就立马创建 bean对象。
实现类:
ClassPathXmlApplicationContext 只能加载类路径下的配置文件
FileSystemXmlApplicationContext 可以加载磁盘任意位置的配置文件
步骤:
1、获取容器
ApplicationContext ac=new ClassPathXmlApplicationContext(“bean.xml”);
2、根据bean的id获取类对象
类名 变量名=(类名)ac.getBean(“”);
代码实现:Spring1项目 Test.Demo02
9.Bean的三种创建方式
Bean对象:也就是bean标签所对应的类对象。即class标签的值。
第一种方式:调用默认无参构造函数创建(开发中用的最多)
默认情况下,如果要创建的类中没有默认无参构造函数,则创建失败,会报异常。
代码实现:Spring1项目 IOCXML.Demo03.test1()
第二种方式:使用静态工厂中的方法创建对象
写法:
代码实现:Spring1项目 Factory.StaticFactory IOCXML.Demo03.test2()
第三种方式:使用实例工厂中的方法创建
写法:
代码实现:Spring1项目 Factory.InstanceFactory IOCXML.Demo03.test3()
10.Bean的作用范围
单例对象作用范围:整个应用
多例对象作用范围:一次使用的过程中
Bean对象可以通过配置的方式来调整作用范围。
配置的属性:bean标签的scope属性
属性的取值:
singleton 单例的(默认值)
prototype 多例的(当我们让spring接管struts2的action创建时,action必须配
置此值)
request 作用范围是一次请求和当前请求的转发。
session 作用范围是一次会话
globalsession 作用范围是一次全局会话。(服务器集群)
代码实现:Spring1项目 IOCXML.Demo04
11.Bean的生命周期
涉及的两个属性:
init-method
destroy-method
因为main出栈后,该线程还没有调用此配置的方法,栈内已经无元素。
单例:
出生:容器创建,对象就出生了
活着:只要容器在,对象就一直存在
死亡:容器销毁,对象消亡
多例:
出生:每次使用时,创建对象
活着:只要对象在使用中,就一直活着
死亡:当对象长时间不使用,并且也没有别的对象引用时,java的垃圾回收器回收
12.Spring的依赖注入
注入的方式有三种:
第一种:使用构造函数注入
第二种:使用set方法注入
第三种:使用注解注入
注入的数据类型有3类:
第一类:基本类型和String类型
第二类:其他bean类型(必须在Spring配置文件中出现过的bean)
第三类:复杂类型(集合类型)
13.Spring的依赖注入—构造函数注入
涉及的标签:
constructor-arg
标签的属性:
type: 指定参数的类型
index: 指定参数的索引位置
name: 指定参数的名称 (一般用它)
====上面三个属性是指定给哪个参数赋值的,下面两个属性是指定赋什么值==
value: 指定基本数据类型或String类型的数据 (直接赋值即可)
ref: 指定其他bean类型数据
标签出现的位置:
写在bean标签内部
案例:使用构造函数注入,注入基本类型和String类型
代码实现:Spring1项目 IOCXML.Demo06
14.Spring的依赖注入—set方法注入
涉及的标签:
Property
当对复杂数据类型进行注入时,需要使用子标签。
结构相同,可以使用结构相同的标签。
子标签:
array
list
map
set
props
标签的属性:
name: 指定参数的set方法名称 (一般用它)
value: 指定基本数据类型或String类型的数据(直接赋值即可)
ref: 指定其他bean类型数据
标签出现的位置:
写在bean标签内部
案例1:使用set方法注入基本数据类型和String数据类型
代码实现:Spring1项目 IOCXML.Demo07
案例2:使用set方法注入复杂数据类型(集合类型)
代码实现:Spring1项目 IOCXML.Demo08
15.SpringProject1项目
目的:对每个变量进行XML-IOC的依赖注入
代码实现:SpringProject1项目
Spring的IOC(注解版)
16.搭建注解版的IOC开发环境
(1)导包
(2)在src下创建bean.xml
17.注解的分类
(1)用于创建bean对象
(2)用于注入数据的
(3)用于改变作用范围的
(4)和生命周期相关的 (了解)
(5)spring的新注解
18.创建bean对象的注解配置
(1)@Component
作用:就相当于一个bean标签。
要求:要调用此类的方法,才让此类进入容器,成为bean对象,由Spring创建。
能出现的位置:类上面
属性:value。
含义是指定bean的id。当不写时,它有默认值,默认值是当前类的类名, 并且首字母小写。
由此衍生的三个注解:
@Controller 一般用于表现层
@Service 一般用于业务层
@Repository 一般用于持久层
它们和@Component的作用及属性都是一模一样的。
(2)< context:component-scan >标签
目的:告知spring在创建容器的时要扫描的包。当配置了此标签后,spring创建容
器就会去指定的包以及子包下找对应的注解。
前提:导入context约束
属性:base-package
告诉spring去哪个包寻找注解
代码实现:Spring2项目
19.注入数据的注解配置
当我们使用注解配置时,set方法不是必须的。
1、复杂数据类型(集合)不能通过注解注入实现。
2、注入其它Bean类型数据:
(1)@Autowired
作用:自动按照类型注入。只要有唯一的类型匹配就能注入成功。
注意:
当类型不是唯一时,会报异常。
当类型不是唯一时,spring会把变量名作为bean的id,在容器中查找。
(2)@Qualifier
作用:在自动按照类型注入的基础上,再按照bean的id注入
属性:value,用于指定Bean的id。
注意:
在给类成员注入数据时,不能独立使用。
在给方法的形参注入数据时,可以独立使用。
在方法形参的最前面使用:
例如:(@Qualifier(“Bean的name值”)DataSource dataSource)
(3)@Resource
作用:根据bean的id注入数据
属性:name,用于指定Bean对象的id
3、注入基本数据类型和String类型
(1)@Value
作用:用于注入基本类型和String类型数据。
它可以借助spring的el表达式读取properties文件中的配置。
属性:value。用于指定要注入的数据。可不写value这几个字母。
20.Bean作用范围的注解配置
@Scope
作用:用于改变Bean的作用范围。
属性:value。用于指定范围的取值
取值和xml中scope属性的取值是一样的。
value的取值:
singleton 单例的(默认值)
prototype 多例的(当我们让spring接管struts2的action创建时,action必须配置此值)
request 作用范围是一次请求和当前请求的转发。
session 作用范围是一次会话
globalsession 作用范围是一次全局会话。(服务器集群)
代码测试:Spring2项目 Service.CustomerService Test.Demo01
21.Bean生命周期的注解配置
@PostConstruct
作用:用于指定初始化方法。
@PreDestroy
作用:用于指定销毁方法
22.Spring的新注解(为了将xml文件完全删除而引出的注解)
(1)@ComponentScan
作用:告诉spring去哪个包寻找注解。相当于
属性:value。可不写。数组类型。指定哪个包。
使用:@ComponentScan({“ ”, ” ”})
使用的位置:类上
(2)@Bean
作用:把方法里的返回值存入spring容器。
属性:name。用于指定bean的id。不写时有默认值,默认值是方法名称
使用的位置:方法上
(3)@Configuration(没有多大的用处)
作用:把当前类看成是Spring的配置类
使用:
将bean.xml放在和配置类同一个包下。
读取容器:new ClassPathXmlApplicationContext(“bean.xml”,配置类名.class);
使用的位置:类上
(4)@Import
作用:导入其他配置类。
属性:value。数组类型。可不写value。指定其它配置类。
使用的位置:配置类上
使用:@import({类名.class})
(5)@PropertySource
作用:用于指定properties文件
属性:value。指定文件的路径。
使用的位置:配置类上
使用:
@PropertySource({“classpath:XX/XXX.properties”})
配合Spring的el表达式。需要解析器解析el表达式。
@Value=(“${key}”) 会自动解析property内的key对应的值
代码实现:SpringProject2项目 Config.SpringConfiguration
23.Spring的EL表达式
Spring 4.3之后的版本自带解析器,来解析EL表达式。
Spring 4.3之前的版本没有自带解析器,需要自己配置。
语法: ${}
自己配置:
在配置类中添加方法。
@Bean
public static PropertySourcesPlaceholderConfigurer create(){
return new PropertySourcesPlaceholderConfigurer();
}
24.java代码创建容器—-注解版
原因:这时没有bean.xml文件存在,所以不能使用
new ClassPathXmlApplicationContext(“bean.xml”);
步骤:
1、获取容器
ApplicationContext ac
=new AnnotationConfigApplicaionContext(SpringConfiguration.class);
2、根据bean的id获取类对象
类名 变量名=(类名)ac.getBean(“”);
代码实现:SpringProject2项目 Test.CustomerServiceTest
25.关于xml和注解的选择问题
Xml:
优点:不需要修改源码
缺点:有的地方会繁琐。如果文件过多时,维护困难。
注解:
优点:清晰明了。
缺点:需要修改源码部分。
选择的原则:
反复要修改配置,选择Xml。
不需要经常修改,选择注解。
26.Spring整合junit单元测试
步骤:
1、导包:spring-test-4.2.4.RELEASE.jar
2、使用junit提供的一个注解,把原来的main函数替换掉,换成spring提供的
@RunWith(SpringJunit4ClassRunner.class)
要换的类:SpringJunit4ClassRunner
3、使用Spring提供的注解告知Spring,配置文件或注解类所在的位置
@ContextConfiguration
如果是配置文件,使用locations
@ContextConfiguration(locations={“classpath:bean.xml”}
如果注解类,使用classes
@ContextConfiguration(classes={XX.class})
原理:
源码:注解存在源码阶段。
编译后:一旦变成字节码class文件,还存在
运行时:进入虚拟机,会出现注解擦除。
代码测试:SpringProject2项目 Test.CustomerServiceTest
27. SpringProject2项目(纯注解版)
目的:对每个变量进行IOC的注解配置
代码实现:SpringProject2项目
动态代理
28.动态代理
作用:不改变源码的基础上,对已有方法的增强。(它是AOP思想的实现技术)
分类:
1、基于接口的动态代理
2、基于子类的动态代理
代理对象:可以理解为“管理对象的类”
29.基于接口的动态代理
代码测试:Spring3项目 proxy包
要求:被代理类至少实现一个接口
提供者:JDK官方
涉及的类:Proxy
创建代理对象的方法:newProxyInstance(ClassLoader,class[],InvocationHandler)
参数的含义:
ClassLoader:类加载器,和被代理对象使用相同的类加载器。
一般都是固定写法。
被代理类的对象.getClass().getClassLoader()
Class[]:字节码数组。被代理类实现的接口。
(要求代理对象和被代理对象具有相同的行为,行为即方法。
也就是实现相同的接口,因而具有相同的方法。)
一般都是固定写法。
被代理类的对象.getClass().getClassLoader().getInterfaces()
InvocationHandler :它是一个接口。就是用于我们提供增强代码的。
我们一般都是写一个该接口的实现类。实现类 可以是匿名内部类。它的含义:如何代理。
此处的代码只能是谁用谁提供。
策略模式:
使用要求:数据已经有了。
目的明确。
达成目标的过程就是策略
在dbUtils中的ResultSetHandler就是策略模式的具体应用。
匿名内部类重写的方法invoke:
执行被代理对象的任何方法都会经过该方法,该方法有拦截的功能。
方法的参数:
Object proxy:代理对象的引用
Method method:当前执行的方法
Object[] args:当前执行方法的参数
返回值:
当前执行方法的返回值
30.基于子类的动态代理
代码测试:Spring3项目 cglib包
要求:被代理类不是最终类,不能被final修饰
提供者:第三方CGLIB
涉及的类:Enhancer
创建代理对象的方法:create(Class,Callback);
参数的含义:
Class:被代理对象的字节码
Callback:如何代理。它和InvocationHandler的作用是一样的。它也是一个接口。
我们一般使用该接口的子接口,即MethodInterceptor。
在使用时我们也是创建该接口的匿名内部类。
匿名内部类重写的方法intercept:
执行被代理对象的任何方法,都会经过该方法。
方法的参数:
Object proxy:代理对象的引用
Method method:当前执行的方法
Object[] args:当前执行方法所需的参数
MethodProxy methodProxy: 当前执行方法的代理对象。一般不用
31.动态代理的具体应用
(1)连接池原理
连接池的close方法不是直接关闭,而是归还给连接池。
这里便使用了动态代理的思想。
(2)实现业务层的事务控制
业务层(Service)不再对事务进行管理。交于代理对象进行管理。
从而实现业务层一个方法内只有一句的代码。
代码实现:Struts2Project1项目 Factory.BeanFactory
Utils.TransactionManager Service.CustomerService
32.什么是AOP
全称:Aspect Oriented Programming 即:面向切面编程。
把重复代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础
上,对我们的已有方法进行增强。
33.AOP的作用及优势
作用:在程序运行期间,不修改源码对已有方法进行增强。
优势:减少重复代码 提高开发效率 维护方便
34.AOP的实现方式
使用动态代理的技术。
AOP(XML版)
35.基于XML文件的AOP配置步骤
第一步:导入jar包
第二步:把通知类交给spring来管理
通知类:增强的代码
第三步:导入AOP名称空间,并且使用aop:config开始AOP的配置
第四步:使用aop:aspect配置切面
切面:增强的代码和需要增强的方法的结合
使用:在aop:config内部使用。属于aop:config的子标签。
属性:
id:用于给切面提供唯一标识。
ref:用于引用通知类bean的id
第五步:配置通知的类型,指定增强的代码何时执行(在
方法执行之前,执行增强的代码:
属性:
method:用于指定增强的方法名称
pointcut:用于指定需要增强的方法。切入点表达式
36.切入点表达式
关键字:execution(表达式)
表达式的写法:
1、全匹配方式
访问修饰符 返回值 包名.类名.方法名(参数列表)
(1)访问修饰符可省略
(2)返回值可以使用通配符,表示任意返回值。
(3)包名可以使用通配符,表示任意包。但是有几个包需要写几个。
例如:三个包:...
(4)包名可以使用..表示当前包及其子包
(5)类名和方法名都可以使用通配符
(6)参数列表可以使用具体类型,来表示参数类型
基本类型直接写类型名称
引用类型必须是包名.类名
(7)参数列表可以使用通配符,表示任意类型。必须有参数
(8)参数列表可以使用.. 表示有无参数均可。参数可以是任意类型
2、全通配方式: ...(..)
实际开发中,我们一般情况下,都是对业务层方法进行增强:
所以写法: Service..(..)
37.配置通用的切入点表达式
如果写在了aop:aspect标签内部,则表示只有当前切面可用。
如果写在了aop:aspect标签外部,则表示所有切面可用。必须写在aop:aspect之前
定义:
标签:aop:pointcut
属性:
expression:切入点表达式
id:指定该通用切入点表达式的唯一标识
使用:
标签:aop:before ,aop:after等
属性:
method:用于指定增强的方法名称
pointcut-ref:用于指定通用的切入点表达式id
38.四种通知类型
前置通知:aop:before
永远在切入点方法之前执行
后置通知:aop:after-returning
切入点方法正常执行之后执行
异常通知:aop:after-throwing
切入点方法产生异常之后执行,它和后置通知永远只有一个
最终通知:aop:after
无论切入点方法是否正常执行,它都会在其后面执行
环绕通知:aop:around
问题:当我们配置了环绕通知,切入点方法没有执行,而环绕通知的代码执行了。
分析:由动态代理可知,环绕通知指的是invoke方法。并且里面有明确的切入点
方法调用,而我们现在的环绕通知没有明确的切入点方法调用。
解决:
Spring为我们提供了一个接口:ProceedingJoinPoint。该接口可以作为环绕
通知的方法参数来使用。在程序运行时,spring框架会为我们提供该接口的
实现类。
该接口中一个方法:proceed()。必须try,catch捕获异常。作用等同于
method.invoke()。就是明确调用业务层的核心方法(切入点方法)
try{
前置代码1;
proceed();
后置代码2;
}catch(Throwable e){
异常代码3;
}finally{
最终代码4;
}
代码测试:Spring3项目 Utils.Logger AOPXML.Client
39.切入点表达式的执行顺序
同种通知表达式,配置在前的先执行。
AOP(纯注解版)
40.配置AOP注解版幻境
1、导入jar包
2、导入约束
40.配置切面
在增强代码的类上方,配置该类为切面。
标签:@Aspect @Component(“”)
使用位置:类上方
代码测试:Spring4项目 Utils.Logger
41.切入点表达式
定义:
@Pointcut(“execution( Service..(..))”)
private void pt1(){}
引用:
@Before(“pt1()”)
代码测试:Spring4项目 Utils.Logger
42.四种通知类型(在方法的上方配置)
前置通知:@Before
永远在切入点方法之前执行
后置通知:@AfterReturning
切入点方法正常执行之后执行
异常通知:@AfterThrowing
切入点方法产生异常之后执行,它和后置通知永远只有一个
最终通知:@After
无论切入点方法是否正常执行,它都会在其后面执行
环绕通知(建议使用):@Around
代码测试:Spring4项目 Utils.Logger
43.开启Spring对注解AOP的支持
在bean.xml文件中:
在配置类上方:@EnableAspectJAutoProxy
代码测试:Spring4项目 bean.xml Config.SpringConfiguration
JdbcTemplate
44.概述
它是Spring框架提供的一个对象,是对原始Jdbc API对象的简单封装。Spring框架
为我们提供了很多的操作模板类。
45.JdbcTemplate的基本用法(不使用配置文件bean.xml)
代码实现:Spring5项目 JdbcTemplate.Demo01
(1)导包
(2)创建连接对象
DriverManagerDataSource ds=new DriverManagerDataSource();
(3)设置四大参数
ds.setDriverClassName(“com.mysql.jdbc.Driver”);
ds.setUrl(“jdbc:mysql://localhost:3306/mydb6”);
ds.setUserName(“root”);
ds.setPassword(“29811055”);
(4)获取JdbcTemplate
JdbcTemplate jt=new JdbcTemplate();
(5)将JdbcTemplate与DataSource关联
第一个方法:jt.setDataSource(ds);
第二个方法:JdbcTemplate jt=new JdbcTemplate(ds);
46.JdbcTemplate的基本用法(使用配置文件bean.xml)
代码实现:Spring5项目 JdbcTemplate.Demo02 bean.xml
(1)导包
(2)配置Bean对象
(3)获取JdbcTemplate
ApplicationContext ac=new ClassPathXmlApplicationContext(“bean.xml”); JdbcTemplate jt=(JdbcTemplate)ac.getBean(“bean的id”);
47.JdbcTemplate的CRUD操作(增,删,改,查)
(1)增(插入数据)
方法:
execute(String sql);
参数:
sql:不带参数的sql语句
update(String sql,Object…params);
参数:
sql:带参数的sql语句
params: sql语句中的参数值,按顺序赋值
代码实现:Spring5项目 JdbcTemplate.Demo03
(2)删(删除数据)
方法:
execute(String sql);
参数:
sql:不带参数的sql语句
update(String sql,Object…params);
参数:
sql:带参数的sql语句
params: sql语句中的参数值,按顺序赋值
代码实现:Spring5项目 JdbcTemplate.Demo04
(3)改(更新数据)
方法:
execute(String sql);
参数:
sql:不带参数的sql语句
update(String sql,Object…params);
参数:
sql:带参数的sql语句
params: sql语句中的参数值,按顺序赋值
代码实现:Spring5项目 JdbcTemplate.Demo05
(4)查(查询数据)
代码实现:Spring5项目 JdbcTemplate.Demo06
1、查询所有或多个
方法:
query(String sql,RowMapper
query(String sql, RowMapper
参数:
sql:不带参数的sql语句
rowMapper:查询结果的结果集
实现类:
BeanPropertyRowMapper
使用:
new BeanPropertyRowMapper<类名>(类名.class)
params:sql语句的参数值,按顺序赋值
返回值:
List
2、查询一个
同上。
3、查询返回一行一列:聚合函数的使用
方法:
queryForObject(String sql,T.Class
(Spring 3.x之后的新方法。)
返回值:T
参数:
sql:带参数的sql语句
type:返回值类型.class
params:sql语句中的参数值,按顺序赋值
queryForInt queryForLong 。。 (Spring 2.x时的方法)
48.JdbcTemplate在dao层中的使用方式1
(1)在dao层创建JdbcTemplate类型的成员变量
(2)set方法或者构造函数注入
(2)在bean.xml配置(不适合使用注解配置)
代码实现:Spring5项目 JdbcTemplate.Demo07 Dao.CustomerDao
49.JdbcTemplate在dao层中的使用方式2
(1)dao继承JdbcDaoSupport
获取JdbcTemplate :getJdbcTemplate();
(2)配置dao层。不需要配置JdbcTemplate。
代码实现:Spring5项目 JdbcTemplate.Demo08 Dao.CustomerDao2
50.JdbcTemplate使用其它数据库连接池
在bean.xml中配置JdbcTemplate,并配置DataSource。
代码实现:Spring5项目 bean.xml
51.使用Spring配置修改Struts2Project1项目
代码实现:SpringProject3项目(纯xml版本)
52.使用Spring配置修改Struts2Project1项目
代码实现:SpringProject4项目(xml和注解版本)
53.使用Spring配置修改Struts2Project1项目
代码实现:SpringProject5项目(纯注解版本)
Spring事务控制
54.概述
(1)事务处理位于业务层(Service层)
(2)Spring框架提供了一组事务控制的接口。在spring-tx-4.2.jar包中
(3)Spring的事务控制都是基于AOP的,可以使用编程实现,也可以使用配置
实现。(重点:配置方式)
55.Spring事务控制的API介绍
(1)PlatformTransactionManager
此接口是Spring的事务管理器。
方法:
1、 获取事务状态信息
TransactionStatus getTransaction(TransactionDefinition definition)
2、 提交事务
void commit(TransactionStatus status)
3、 回滚事务
void rollback(TransactionStatus status)
实现类:
DataSourceTransactionManager
使用SpringJDBC或iBatis进行持久化数据时使用
HibernateTransactionManager
使用Hibernate5.0版本进行持久化数据时使用
(2)TransactionDefinition
事务的定义信息对象。
方法:
1、获取事务名称
String getName()
2、获取事务隔离级别
int getIsolationLevel()
事务的隔离级别:
事务隔离级别反映事务提交并发访问时的处理态度。
(1)SERIALIZABLE串行化(可以解决三种读问题):
1. 不会出现任何并发问题。因为它对同一数据的访问是串行的。
2. 性能最差。
(2)REPEATABLE READ可重复读(MySql默认):
1.防止脏读和不可重复读
2. 性能比SERIALIZABLE好
(3)READ COMMITTED读已提交数据(Oracle默认):
1. 只能处理脏读
2. 性能比REPEATABLE READ好
(4)READ UNCOMMITTED(读未提交数据):
1. 可能出现任何事物并发问题
2. 性能最好
3、获取事务传播行为
int getPropagationBehavior()
事务的传播行为:
(1)REQUIRED:如果当前没有事务,就创建一个事务。如果已经存在一个
事务中,加入到这个事务中。一般的选择(默认值)增,删,改方法。
(2)SUPPORTS:支持当前事务。如果当前没有事务,就以非事务方式执行。
查询方法
4、获取事务超时时间
int getTimeout()
事务的超时时间:
默认值是-1,没有超时限制。如果有,以秒为单位进行设置。
5、获取事务是否只读
boolean isReadOnly()
读写型事务:增加、删除、修改开启事务
只读性事务:执行查询时,包含开启事务(查询时设置为只读)
(3)TransactionStatus
描述了某个时间点上事务对象的状态信息。
方法:
1、刷新事务
void flush()
2、获取是否存在存储点
boolean hasSavepoint()
3、获取事务是否完成
boolean isCompleted()
4、获取事务是否为新的事务
boolean isNewTransaction()
5、获取事务是否回滚
boolean isRollbackOnly()
6、设置事务回滚
void setRollbackOnly()
56.Spring的事务控制—-搭建环境(使用xml配置)
(1)导入jar包
(2)bean.xml文件导入约束
57.案例1:模拟转账。
代码实现:Spring6项目
(3)创建Domain包
在Domain包下创建实体类。与数据库相对应。
(4)创建Dao层和Service层
Dao层下创建AccountDao类,继承JdbcDaoSupport类。
配置AccountDao。
配置AccountService。
(5)在Test.Client测试类中 测试Service层(业务层)的转账方法transfer()
结论:有异常的情况下,转账必须失败。但是这里还没有配事务,会出现问题。
58.Spring基于XML的声明式事务的配置(纯XML版)
代码实现:Spring7项目
(1)搭建事务配置的环境
略
(2)创建Domain,Dao,Service包和Acount,AcountDao,AcountService类。
此处AccountDao继承JdbcDaoSupport。不需要有JdbcTemplate类型的成员变量
(3)进行Spring的IOC配置(使用XML配置)
第一步:配置Service层。(略)
第二步:配置Dao层。
第三步:配置Spring内置的DataSource(略)
(4)基于XML的声明式事务控制
第一步:配置事务管理器。
第二步:配置事务的通知。(对应AOP的通知类)
不需要配置切面AOP,Spring会自动提交和回滚事务。
第三步:配置aop
<!—切入点表达式 —>
<!—配置事务通知和切入点表达式的关联 —>
第四步:配置事务的属性。在tx:advice标签内配置。
用法:
标签:
作用:用于指定某个方法内,事务的属性。
属性:
name:指定哪个方法。优先级:<find
isolation:配置事务的隔离级别。默认值:DEFAULT,使用数据库的默
认隔离级别。Mysql是REPEATABLE_READ
propagation:配置事务的传播行为。默认值:REQUIRED。一般的选择。
(增删改方法)。查询方法时,选择SUPPORTS
timeout:指定事务的超时时间。默认值:-1,永不超时。当指定其它
值时,以秒为单位。
read-only:配置是否是只读事务。默认值:false,读写型事务。当
指定为true时,表示只读,只能用于查询方法。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。
产生其它异常时,事务不回滚。没有默认值,任何异
常都回滚。
no-rollback-for:用于指定一个异常,当执行产生该异常时,事务不
回滚。产生其它异常时,事务回滚。没有默认值,任何异常都回滚。
59.Spring基于XML和注解组合的声明式事务的配置(XML和注解组合)
代码实现:Spring8项目
(1)搭建事务配置的环境(略)
(2)创建Domain,Dao,Service包和Acount,AcountDao,AcountService类。
此处AccountDao要有JdbcTemplate类型的成员变量 直接@Autowired
(3)进行Spring的IOC配置(使用注解配置)
第一步:配置Service层。(略)
第二步:配置Dao层。(略)
在bean.xml中需要配置jdbcTemplate。
第三步:配置Spring内置的DataSource(略)
(4)基于XML和注解组合的配置步骤
第一步:配置事务管理器(XML)
第二步:配置Spring开启注解事务的支持(XML)
第三步:在需要事务的地方使用@Transactional注解(一般都是Service层)
@Transactional的使用位置:接口上,类上,方法上。
写在接口上,表示该接口的所有实现类都有事务。
写在类上,表示该类的所有方法都有事务。
写在方法上,表示该方法有事务。
优先级:方法上>类上>接口上
属性:
isolation:配置事务的隔离级别。默认值:DEFAULT,使用数据库的默
认隔离级别。Mysql是REPEATABLE_READ
propagation:配置事务的传播行为。默认值:REQUIRED。一般的选择。
(增删改方法)。查询方法时,最好选择SUPPORTS
timeout:指定事务的超时时间。默认值:-1,永不超时。当指定其它
值时,以秒为单位。
read-only:配置是否是只读事务。默认值:false,读写型事务。当
指定为true时,表示只读,只能用于查询方法。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。
产生其它异常时,事务不回滚。没有默认值,任何异
常都回滚。
no-rollback-for:用于指定一个异常,当执行产生该异常时,事务不
回滚。产生其它异常时,事务回滚。没有默认值,任何异常都回滚。
60.Spring基于注解的声明式事务的配置(纯注解配置)
代码实现:Spring9项目
(1)搭建事务配置的环境(略)
(2)创建Domain,Dao,Service包和Acount,AcountDao,AcountService类。
此处AccountDao要有JdbcTemplate类型的成员变量 直接@Autowired
(3)进行Spring的IOC配置(使用注解配置)
第一步:配置Service层。(略)
第二步:配置Dao层。(略)
在bean.xml中需要配置jdbcTemplate。
第三步:配置Spring内置的DataSource(略)
(4)基于注解的配置步骤
第一步:创建Config包,在包下创建SpringConfiguration核心配置类。
在类上配置要扫描的包和导入其他配置类。
要扫描的包:@ConponentScan({“Service”,”Dao”})
导入其它配置类:Import({JdbcConfig.class,
TransactionManager.class})
开启Spring对注解事务的支持:@EnableTransactionManagement
第二步:在Config包下创建连接数据库的配置类。class JdbcConfig
在类的内部写带有返回值的二个方法:
@Bean(name=”jdbcTemplate”)
public JdbcTemplate 方法名(DataSource dataSource)
{
Return new JdbcTemplate(dataSource);
}
@Bean(name=”dataSource”)
public DataSource 方法名(DataSource dataSource)
{
DriverManagerSource ds=new DriverManagerDataSource(); //用set方法设置连接数据库的四大参数
(略)
return ds;
}
第三步:在Config包下创建事务管理器的配置类。class TransactionManager 在类的内部写带有返回值的方法:
@Bean(name=”transactionManager”)
public PlatformTransactionManager getTransactionManager
(DataSource dataSource)
{
return new DataSourceTransactionManager(dataSource);
}
第四步:在需要事务的地方使用@Transactional注解(一般都是Service层)
SSH整合
61.整合三个版本
第一个版本:纯XML的整合。保留spring,struts2,hibernate各自的主配置文件。
第二个版本:纯XML的整合。保留spring和struts2的主配置文件,hibernate的
主配置文件内容配到spring的配置文件中。
第三个版本:XML和注解的组合式整合。仅保留spring的主配置文件(根据实际开发
的需要,struts2的配置文件也可以保留。)
版本选择:
第一个版本和第二个版本任意选择一个。
第三个版本就一定要会。
62.整合步骤
第一步:保证spring的ioc容器能够在web工程中独立运行。
第二步:保证hibernate框架能够在web工程中独立运行。
第三步:整合spring和hibernate
1、Spring接管了hibernate的sessionFactory对象创建(把seesionFactory存
入Spring容器中)
2、使用了spring的声明式事务控制
第四步:保证struts2框架能够在web工程中独立运行
第五步:整合spring和struts2
1、action的创建交给spring来管理
2、保证web工程的容器只有一个
第六步:优化已有的整合配置
1、配置文件的位置存放可以调整
2、配置文件的内容可以分不同文件来编写
63.第一个版本的整合 代码实现:SSH01项目
整合步骤的第一步:
1、编写Domain包下的客户实体类
2、编写Service和Dao层(还没有实现功能)
3、导入Spring的IOC,AOP,事务控制的相关jar包
4、在src下创建bean.xml并导入AOP和IOC有关的约束
配置Service层和Dao层
5、测试spring的ioc容器是否能够在web工程中独立运行?
代码测试:Tes.Test01Spring
整合步骤的第二步:
1、搭建hibernate的开发环境,导入jar包
2、在Domain包下创建映射配置文件(实体类类名.hbm.xml)
导入约束:
约束的路径:hibernate-core/org.hibernate/hibernate-mapping-3.0.dtd
配置实体类映射。(略)
3、在src下创建主配置文件(hibernate.cfg.xml)
编写主配置文件(略)
4、测试hibernate框架是否能够在web工程中独立运行?
代码测试:Test.Test02Hibernate
整合步骤的第三步:
1、实现Dao层的功能。
在CustomerDao类:
创建HibernateTemplate类型的成员变量,并带set方法。
原因:该类型是spring提供的,是对hibernate的session对象进
行了简单的封装。包为:hibernate5.HibernateTemplate
方法:
保存:hibernateTemplate.save(Object obj);
查询:hibernateTemplate.find(HQL语句);
返回值:List
2、在baen.xml中配置HibernateTemplate
3、在bean.xml配置SessionFactory。即由Spring接管SessionFactory的创建。
(1)用Spring提供的SessionFactory:LocalSessionFactoryBean
(2)常见SessionFactory有三部分必不可少的信息。信息都在hibernate主
配置文件中。所以把Hibernate的主配置文件注入进去。
4、在bean.xml配置spring的声明式事务控制
(1)配置事务管理器。此处使用HiberbateTransactionManager
(2)配置事务的通知(略)
(3)配置事务的aop (略)
5、使用Spring的配置把session和线程绑定
原因:Spring不支持Hibernate中session和线程绑定的配置
解决的办法:将Hibernate原先的配置删去。Spring的HibernateTemplate 默认将session和线程绑定了。无需配置。
整合步骤的第四步:
1、搭建struts2的开发环境并测试(略)
2、编写Action动作和配置(略)
3、配置Spring提供的监听器。(Servlet自带8大监听器)
原因:动作类是多例的,每次都会创建新的容器,导致容器的bean也会
创建新的。
目的:应用加载时,创建CustomerService。应用结束时,销毁CustomerService 应用加载,ServletContext创建。
配置:
1、导入jar包。
spring-web.jar
2、在web.xml内配置spring提供的监听器。用于监听ServletContext 对象的创建,同时为我们创建spring的容器。
org.springframework.web.context.ContextLoaderListener
3、创建Spring的容器后,为了下次可以再用,Spring替我们将容器
存在了应用域中。
获取ServletContext:
ServletContext application=
ServletActionContext.getServletContext();
获取Spring容器:
ApplicationContext ac=WebApplicationContextUtils.
getWebApplicationContext(application);
获取bean对象:
ac.getBean(“customerService”)
4、ServletContextListener监听器
默认情况下:只能加载位置是在WEB-INF目录中的Spring配置文件,
同时文件名称必须是applicationContext.xml
所以修改bean.xml文件的位置和名称。
整合步骤的第五步:
1、导入jar包
struts2-spring-plugin-2.3.24.jar
2、Action类必须要有Service的set方法。
(1)原来创建action的类是struts2提供的。
(2)导入jar包后,类改变了,它会自动加载容器和调用set方法。
原因:jar包内有一个配置文件,会覆盖struts-default的配置。
(3)Action类的构造函数不需要写以下的任何方法。
64.第二个版本的整合 代码实现:SSH02项目
说明:其余的配置不再重复。此项目是基于SSH01的基础上作修改的。
1、将Hibernate主配置文件中的内容都交给Spring来管理。删除Hibernate主配置文件也就是在applicationContext.xml中配置Hibernate主配置文件中的内容。
(1)首先将bean.xml中配置了hibernate主配置文件的位置的语句删了。
删掉:
(2)配置第一部分:数据库的连接池
接着配置dataSource。(略)
(3)配置第二部分:hibernate的可选配置。因为都是键值对类型。
使用
(4)配置第三部分:映射文件的位置
写法:
name属性取值:
mappingResources:它是一个注入String数组类型的数据。提供的是
映射文件的位置。有几个映射文件,就需要写几个。
mappingDirectoryLocations:它是注入一个Resource类型的数据。提供
的是映射文件的目录。此属性一般多用于一个项目有多个地方存放映射配置。
//服务端
Server_domain
//移动端
Mobile_domain
mappingLocations:它是注入一个Resource类型的数据。提供的是映射
文件的位置。它可以使用通配符。
配置:
2、优化:手动指定Spring配置文件applicationContext.xml的位置
原因:Spring提供的ServletContext监听器会自动加载配置文件。
解决的办法:设置ServletContext的初始化参数。来指定配置文件的位置。 配置:在web.xml文件内进行配置。
3、优化:手动指定Stuts2配置文件struts.xml的位置
原因:struts2的核心过滤器会自动加载struts2的配置文件
解决的办法:设置struts2核心过滤器的参数。此处的配置大多都是固定的。 配置:在web.xml文件内的struts2核心过滤器的filter标签内进行配置。
struts-default.xml,struts-plugin.xml,Config/struts.xml
/*
蓝色字体:如果用了struts2-spring-plugin-2.3.24.jar包,就必须写。
红色字体:自己指定的struts.xml的位置。
4、优化:将applicationContext.xml的配置分开编写
(1)创建application-customer.xml。配置和Customer相关的bean
配置Service层和Dao层(略)
(2)创建applicationContext-jdbc.xml。配置和JDBC相关的。
配置HibernateTemplate,sessionFactory,dataSource(略)
(3)创建applicationContext-tx.xml.配置和事务相关的。
配置事务管理器,事务的通知,事务的aop(略)
(4)最后将applicationContext.xml中的所有配置删除。只需要引入以上三
个配置文件。
写法:
5、优化:将struts.xml的配置分开编写
(1)创建struts-customer.xml。配置和Customer相关的动作。
配置Action包中类的动作方法。(略)
修改Action的继承包。
struts-default—myDefault
(2)最后将struts.xml中关于动作方法的配置删除。
配置开发者模式。
配置公共包。公共的配置都写在struts.xml文件中。
引入其他的struts2的配置文件。
6、优化:使用HibernateDaoSupport。
因为:如果有多个XXXDao类。那么以下代码就是重复代码。
private HibernateTemplate hibernateTemplate;
public void set HibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate=hibernateTemplate;
}
解决办法:Dao类继承HibernateDaoSupport。
获取HibernateTemplate的方法:getHibernateTemplate();
配置:
1、在applicationContext-jdbc.xml中删除hibernateTemplate的配置。
2、在applicationContext-customer.xml中修改Dao层的配置。
7、优化:Spring接管Action的创建。
(1)在applicationContext-customer.xml配置文件中,配置Action。
(2)在struts-customer.xml配置文件中,修改原有的配置。
将action标签的class属性值改为:customerAction。也就是Action的id
65.第三个版本的整合 代码实现:SSH03项目
说明:其余的配置不再重复。此项目是基于SSH01的基础上作修改的。
1、优化:手动指定Spring配置文件applicationContext.xml的位置
原因:Spring提供的ServletContext监听器会自动加载配置文件。
解决的办法:设置ServletContext的初始化参数。来指定配置文件的位置。 配置:在web.xml文件内进行配置。
2、使用注解配置Service层和Dao层和Action类,并删除相关的xml配置(略)
3、在applicationContext.xml中配置Spring创建容器时要扫描的包(略)
4、删除事务aop的xml配置,使用注解配置事务通知。(略)
5、将Hibernate主配置文件中的内容都交给Spring来管理。(第二个版本有,此处略)
6、删除实体类的映射配置文件,使用注解配置实体类。(JPA注解配置,此处略)
7、修改applicationContext.xml中关于配置映射文件位置。
配置:
packagesToScan的作用:指定实体类所在的包,当创建SessionFactory,会去该
包中扫描实体类上的注解,从而生成映射配置。
8、使用注解配置struts.xml配置文件的所有内容
(1)导入jar包:struts2-convention-plugin-2.3.24.jar
(2)删除struts.xml配置文件。
(3)在Action类中使用注解配置动作方法和结果视图。
(4)在web.xml中的filter标签内配置开发者模式和注解的位置
开启开发者模式
指定注解的位置