Spring学习(黑)
- 1.spring程序开发步骤
1.导入spring开发的基j本包坐标
spring-context
2.编写Dao接口和实现类
创建bean
3.创建spring核心配置文件
applicationContext.xml
4.在Spring配置文件中配置UserDaoImpl
5.使用spring的api获得Bean实例
2.Bean标签基本配置
用于配置对象交由Spring来创建
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数,则不能创建成功
基本属性:
- id:Bean实例在spring容器中唯一标识
- class:Bean的全限定名称
scope:指定对象的作用范围,
取值:
取值范围 | 说明 |
singleton | 默认值,单例的 |
prototype | 多例的 |
request | WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中 |
session | WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中 |
global session | WEB项目中,应用Protlet环境,如果么有Portlet环境nameglobalSession相当于session |
Bean标签范围配置:
- 当scope的取值为singleton时
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期:
-
-
- 对象创建:当应用加载,创建容器时,对象被创建了
- 对象运行:只要容器在,对象一直活着
- 对象销毁:当应用卸载,销毁容器时,对象被销毁了
-
2.当scope的取值为prototype时
Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean
-
-
- 对象创建:当使用对象时,创建新的对象实例
- 对象运行:只要对象在使用中,就一直活着
- 对象销毁:当对象长时间不用时,被java的垃圾回收器回收了
-
3.Bean生命周期
-
-
- init-method:指定类中的初始化方法名称
- destroy-method:指定类中销毁方法名称
-
3.4Bean实例化的三种方式:
- 无参构造方法实例化
- 工厂静态方法实例化 : spring.xml中
<bean id="userDao" class="com.itheima.factory.StaticFactory" factory-method="getUserDao"/>关键是factory-method表示获取对象userDao通过factory-method来获取
- 工厂实例方法实例化
<!--创建工厂对象--> <bean id="factory" class="com.itheima.factory.DynamicFactory"/> <!--根据工厂对象创建userDao对象--> <bean id="userDao" factory-bean="factory" factory-method="getUserDao"
3.6Bean的依赖注入分析
目前UserService实例和UserDao实例都存在与Spring容器中,当前的做法是在容器外部获得UserService,实例和UserDao实例,然后在程序中进行结合.
3.7Bean的依赖注入概念:
依赖注入(Dependency Injection):它是Spring框架核心IOC的具体实现
在编写程序时,通过控制反转,把对象的创建交给了Spring,但是代码中不可能出现没有依赖的情况
IOC解耦只是降低他们的依赖关系,但不会消除.例如:业务层扔会调用持久层的方法
那种业务层和持久层的依赖关系,在使用spring之后,就让spring来维护了.
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取
怎么将UserDao怎样注入到UserService内部呢?
- 构造方法
- set方法
3.7Bean的依赖注入方式
- set方法注
P命名空间注入本质是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:
xmlns:p="http://www.springframework.org/schema/p"
其次,需要修改注入方式
<bean id="userService" class="com.itheima.impl.UserServiceImpl" p:userDao-ref="userDao"/>
3.8Bean的依赖注入的数据类型
上面的操作,都是注入的引用Bean,处了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入
3.9引入其他配置文件(分模块开发)
实际开发中,Spring的配置内容非常多,这就导致了Spring配置很复杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而Spring主配置文件通过import标签进加载
<import resource="applicationContext-xxx.xml"/
知识要点:
Spring的重点配置
<bean>标签
id属性:在容器中Bean实例的唯一标识,不允许重复
class属性:要实例化的Bean的全限定名
scope属性:Bean的作用范围,常用是Singleton(默认)和prototype
<property>标签:属性注入
name属性:属性名称
value属性:注入的普通属性值
ref属性:注入的对象引用值
<list>标签
<map>标签
<properties>标签
<constructor-arg>标签
<import>标签:导入其他的Spring的分文件
Spring相关API
4.1ApplicationContext的继承体系
applicationContext:接口类型,代表应用上下文,可以通过其实例获得Spring容器中的Bean对象
4.2ApplicationContext的实现类
- ClassPathXMLApplicationContext
它是从类的根路径下加载配置文件推荐使用这种
2.FileSystemXmlAplicationContext
它是磁盘路径下加载配置文件,配置文件可以在磁盘的任意位置
3.AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用类来创建spring容器,它用来读取注解
4.3getBean()方法使用
4.4Spring的重点APi
ApplicationContext app=new ClassPathXmlApplicationContext("xml文件") app.getBean("id") app.getBean(Class)
1.1数据源(连接池)的作用
- 数据源(连接池)是提高程序性能而出现的
- 事先实例化数据源,初始化部分连接资源
- 使用连接资源时从数据源中获取
- 使用完毕后将连接资源归还 给数据源
常见的数据源(连接池):DBCP,C3P0,BoneCP,Druid
配置数据源的步骤:
1.添加包
mysql-connector-java(5.1.32)
C3P0(0.9.1.2)
druid(1.1.10)
C3P0手动配置//测试手动创建c3p0数据源
//C3po手动配置
pubic void test3() throws Exception(){
//读取配置文件jdbc.properties,
ResouceBundle rb=ResourceBundle.getBundle("jdbc");
String driver=rb.getString("jdbc.driver");
String url=rb.getString("jdbc.url");
String username=rb.getString("jdbc.username");
String password=rb.getString("jdbc.password");
//创建数据源对象,设置连接参数
ComboPooleDataSource dataSource=new ComboPooleDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url)
dataSource.setUser(username);
dataSource.setPassword(password);
Connection connection=dataSource.getConnection()
System.out.println(connection);
connnection.close();
}
public void test1() throws Exception{ ComboPooleDataSource dataSource=new ComboPooleDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test") dataSource.setUser("root"); dataSource.setPassword("root"); Connection connection=dataSource.getConnection() System.out.println(connection); connnection.close();
} }
测试手动创建druid数据源
public void test2() throws Exception{ DruidDataSource dataSource=new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl(jdbc:mysql://localhost:3306//test); dataSource.setUserName("root"); dataSource.setPassword("root"); DruidPooledConnection connection=dataSource.getConnection(); System.out.prinxtln(connection); connection.close(); }
1.Spring配置数据源
可以将DataSoure的创建权交由Spring容器去完成
<!--加载外部的数据库配置文件jdbc.properties文件-->
<context:property-placeholder location=",classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}"/> </bean>
2.Spring注解开发
2.1Spring原始注解
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置,文件可以简化配置,提高开发效率
Spring原始注解主要是替代<Bean>的配置
注解 | 说明 |
@Component | 使用在类上用于实例化Bean |
@Controller | 使用在web层类上用于实例化Bean |
@Service | 使用在service层类上用于实例化Bean |
@Repository | 使用在dao层类上用于实例化Bean |
@AutoWired | 使用在字段上用于根据类型依赖注入 |
@Qualifier | 结合@Autowired一起使用用于根据名称进行依赖注入 |
@Resource | 相当于@Autowired+@Qualifier,按照名称进行注入 |
@Value | 注入普通属性 |
@Scope | 标注Bean的作用范围 |
@PostConstruct | 使用在方法上,标注该方法是Bean的初始化方法 |
@PreDestroy | 使用在方法上,标注该方法是Bean的销毁方法 |
2.1Spring原始注解
注意:
使用注解进行开发时,需要applicationContext.xml中配置组件扫描,作用是指定哪个包及其字包 下的Bean需要进行扫描以便识别使用注解配置的类,字段和方法
<!--注解的组件扫描--> <context:component-scan base-package="com.itheima"/>
注入:
@AutoWired//按照数据类型从Spring容器中进行匹配的
@Qulifier("userDao")//是按照id值从容器中进行匹配的,但是主要此处@Qulifier结合@Autowired一起使用的
@Resource(name="userDao")//@Resource相当于@Qualifier+@Autowired
@Value("itcast")//普通类型注入
@scope//
2.2spring新注解
使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:
- 非自定义的Bean的配置:<bean>
- 加载properties文件的配置:<context:property-placeholder>
- 组件扫描的配置:<context:component-scan>
- 引入其他文件:<import>
注解 | 说明 |
@Configuration | 用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解 |
@ComponentScan |
用于指定Spring在初始化容器时要扫描的包 作用和在Spring的xml配置文件中的 <context:conponent-scan base-packeage="com.itheima"/>一样 |
@Bean | 使用在方法上,标注将该方法的返回值存储到Spring容器中 |
@PropertySource | 用于加载properties文件中的配置 |
@import | 用于导入其他配置类 |
@Configuration:表示该类时Spring的核心配置类
@Component("com.itheima"):表示扫描包com.itheima
package com.yyp.configuration; import java.beans.PropertyVetoException; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration // 表示该类时Spring的核心配置类 @ComponentScan("com.yyp.dao") // 表示扫描包路径com.itheima public class SpringConfiguration { @Bean("dataSource") // Spring会将当前方法的返回值以指定名称存储到spring容器中去 public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:myql://localhost:3306/test"); dataSource.setUser("root"); dataSource.setPassword("12345678"); return dataSource; } }
数据库的jdbc.properties配置文件也放进了注解中
package com.yyp.configuration; import java.beans.PropertyVetoException; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration // 表示该类时Spring的核心配置类 @ComponentScan("com.yyp.dao") // 表示扫描包路径com.itheima @PropertySource("classpath:jdbc.properties") // 加载数据库配置文件到容器中 public class SpringConfiguration { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean("dataSource") // Spring会将当前方法的返回值以指定名称存储到spring容器中去 public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver); dataSource.setJdbcUrl(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource; } }
通过注解方式的容器加载配置类:
ApplicationContext ac=new AnnotationConfigApplicationContext(SpringConfiguration.class)
//通过容器获得bean
UserService userService=app.getBean(UserService.class)
userService.save();
3.1原始Junit测试Spring的问题
在测试类中,每个测试方法都有一下两行代码
ApplicationContext ac=new ClassPathXmlApplicationContext(""bean.xml""); IAccountService as=ac.getBean("accountService",IAccountService.class)
这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常,所以又不能轻易删除掉
3.2上述问题解决思路
- 让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
- 将需要进行测试Bean直接在测试类中进行注入
3.3Spring集成Junit
- 导入spring集成Junit的坐标
- 使用@Runwith注解替换原来的运行期
- 使用@ContextConfiguration指定配置文件或配置类
- 使用@Autowired注入需要测试的对象
- 创建测试方法进行测试
Spring的AOP简介
1.1什么是AOP
AOP是Aspect Oriented Programming的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
1.2AOP的作用及其优势
*作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
*优势:减少重复代码,提供开发效率,便于维护
1.3AOP的底层实现
AOP的底层是通过SPring提供的动态代理技术实现的,在运行期间,spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调目标对象的方法,从而完成功能的增强
1.4AOP的动态代理技术
常用的动态代理技术:
-
-
- JDK代理:基于接口的动态代理技术
- cglib代理:基于父类继承的动态代理技术
-
1.5JDK动态代理
1.6cglib代理
1.7AOP相关概念
Spring的AOP实现底层就是对上面动态代理的代码进行封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定的目标的方法增强
在正式讲解aop之前,我们必须理解aop的相关术语,常用的术语如下:
- Target(目标对象):代理的目标对象
- Proxy(代理):一个类比aop织入增强后,就产生一个结果代理类
- Joinpoint(连接点):所谓连接点是指哪些被拦截到的点.在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
- Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
- Advice(通知/增强):所谓通知时指拦截到Joinpoint之后所要做的事情就是通知
- Aspect(切面):是切入点和通知(引介)的结合
- Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
1.8AOP开发明确的事项
1.需要编写的内容
-
-
- 编写核心业务代码(目标类的目标方法)
- 编写切面类,切面类中有通知(增强功能方法)
- 在配置文件中,配置织入关系,即将哪些通知与哪些连接点进行结合
-
2.AOP技术实现的内容
Spring框架监控切入点方法的执行,一旦监控到切入点方法被执行,使用代理机制,动态创建啊目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行.
3.AOP底层使用哪种代理方式
在spring中,框架会根据目标类是否实现了接口决定采用哪种动态代理的方式
知识要点:
- aop:面向切面编程
- aop底层实现:基于jdk的动态代理和基于cglib的动态代理
- aop重点概念
-
- Pointcut(切入点):被增强的方法(普通方法,业务方法)
- Advice(通知/增强):封装增强业务逻辑的方法(增强方法)
- Aspect(切面):切点+通知(普通方法+增强方法)
- Weaving(织入):将切点和通知结合的过程
-
- 开发明确事项:
-
- 谁是切点(切点表达式配置,普通方法)
- 谁是通知(切面类中的增强方法.就是增强方法)
- 将切点和通知进行织入配置
-
2.1快速入门
- 导入AOP相关坐标:spring-context(5.0.5.RLEASE)和aspectJweaver(1.8.4)
- 创建目标接口和目标类(内部有切点)
- 创建切面类(内部有增强方法)
- 将目标类和切面类的对象创建权交给spring
- 在ApplicationContext.xml中配置织入关系
<!--目标对象--> <bean id="target" class="com.itheima.aop.Target"/> <!--切面对象--> <bean id="myAspect" class="com.itheima.aop.MyAspect"/> <!--配置织入:告诉spring--> <!--配置织入:告诉spring框架,哪些方法(切点)需要进行哪些增强(前置,后缀...环绕)--> <aop:config> <!--声明切面--> <aop:aspect ref="myAspect"> <!--切面,切点+通知--> <aop:before method="before" pointcut=""execution(public void com.itheima.aop.Target.save()/>
</aop:aspect>
<aop:config>
- 在ApplicationContext.xml中配置织入关系
- 测试代码
2.2XML配置AOP详解
1.切点表达式的写法
表达式语法:
excution([修饰符]返回值类型 包名.类名.方法名(参数))
-
-
- 访问修饰符可以省略
- 返回值类型,包名.类名.方法名可以使用星号*代表任意
- 包名和类名之间一个点.代表当前包下的类,连个点..表示前包及其子包下的类
- 参数列表可以使用两个点..表示任意个数,任意类型的参数列表
-
例如:
execution(public void com.itheima.aop.Target.method)) execution(void com.itheima.aop.Target.*(..)) execution(* com.itheima.aop.*.*(..)) execution(* com.itheima.aop..*.*(..)) execution(* *..*.*(..))
2.2XML配置AOP类型
2.通知的类型
通知的配置语法:
<aop:通知类型 method="切面类中方法名" pointcut="切点表达式"></aop:通知类型>
名称 | 标签 | 说明 |
前置通知 | <aop:before> | 用于配置前置通知.指定增强的方法在切入点方法之前执行 |
后置通知 | <aop:after-returning> | 用于配置后置通知.指定增强的方法在切入点方法之后执行 |
环绕通知 | <aop:around> | 用于配置环绕通知.指定增强的方法在切入点方法之前后之后都执行 |
异常抛出通知 | <aop:throwing> | 用于配置异常抛出通知.指定增强方法在出现异常时执行 |
最终通知 | <aop:after> | 用于配置最终通知.无论增强方式执行是否有异常都会执行 |
3.切点表达式的抽取
当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用pointcut-ref属性代替pointcut属性来引用抽取后的切点表达式
<aop:config> <!--引用myAspect的Bean为切面对象--> <aop:aspect ref="myAspect"> <aop:pointcut id="myPointcut" expresssion="execution( * com.itheima.apop.*.*(..)"/> <aop:before method="before" pointcut-ref="myPointout"/> </aop:aspect> </aop:config>
2.3知识要点
- aop织入的配置
<aop:config> <aop:aspect ref="切面类"> <aop:before method=""通知方法名称" pointcut="切点表达式"/> </aop:aspect> </aop:config>
- 通知的类型:前置通知,后置通知,环绕通知,异常抛出通知,最终通知
- 切点表达式的写法
execution([修饰符]返回值类型 包名.类名.方法名(参数))
3.基于注解的AOP步骤
3.1快速入门
基于注解的aop开发步骤:
- 创建目标接口和目标类(内部有切点)
- 创建啊切面类(内部有增强方法)
- 将目标类和切面类的对象创建权交给spring
- 在切面类中使用注解配置织入关系
- 在配置文件中开启组件扫描和AOP的自动代理
<!--组件扫描--> <context:component-scan base-package="com.itheima.anno"/> <!--aop自动代理--> <aop:aspectj-autoproxy/>
- 测试
3.2注解配置AOP详解
1.注解通知的类型
通知的配置语法:@通知注解("切点表达式")
名称 | 注解 | 说明 |
前置通知 | @Before | 用于配置前置通知,指定增强的方法在切入点方法之前执行 |
后置通知 | @AfterReturning | .用于配置后置通知,指定增强的方法在切入点啊方法之后执行 |
环绕通知 | @Around | 用于配置环绕通知.指定增强的方法在啊切入点之前和之后都行 |
异常抛出通知 | @AfterThrowing | 用于配置异常抛出通知,指定增强的发放在出现异常时执行 |
最终通知 |
@After |
用于配置最终通知,无论增强方式执行是否有异常都会执行 |
2.切点表达式的抽取
同xml配置aop一样,我们可以将切点表达式抽取.抽取方式是在切面内定义方法,在该方法上使用@Pointcut
注解定义切点表达式,然后在增强注解中进行引用,具体如下:
知识要点
- 注解aop开发步骤
- 使用@Aspect标注切面类
- 使用@通知注解标注通知方法
- 在配置文件中配置aop自动代理<aop:aspectj-autoproxy/>
名称 注解 说明 前置通知 @Before 用于配置前置通知.指定增强的方法在切入点方法之前执行 后置通知 @AfterReturning 用于配置后置通知.指定增强的方法在切入点方法之后执行 环绕通知 @Around 用于配置环绕通知.指定增强的方法在切入点方法之前和之后都执行 异常抛出通知 @AfterThrowing 用于配置异常抛出通知.指定增强的方法在出现异常时执行 最终通知 @After 用于配置最终通知,无论增强方式执行是否有异常都会执行
1.Spring JdbcTemplate基本使用
1.1JdbcTemplate概述
它是spring框架中提供的一个对象,是对原始繁琐的jdbcAPI对象的简单封装.sprig框架为我们提供了很多的操作的模板类.
例如:操作关系型数据的jdbcTemplate和HibernateTemplate,操作nosql数据库的RedisTemplate,操作消息队列的JmsTemplate等等
Spring JdbcTemplate基本使用:
JdbcTemplate开发步骤:
- 导入spring-jdbc和spring-tx坐标以及mysql驱动
- 创建数据库表和实体
- 创建jsbcTemplate对象
- 执行数据库操作
package com.yyp.c3p; import java.beans.PropertyVetoException; import org.springframework.jdbc.core.JdbcTemplate; import com.mchange.v2.c3p0.ComboPooledDataSource; public class App { public static void main(String[] args) { // 创建C3P0数据源对象 ComboPooledDataSource dataSource = new ComboPooledDataSource(); try { dataSource.setDriverClass("com.mysql.jdbc.Driver"); } catch (PropertyVetoException e) { e.printStackTrace(); } dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring"); dataSource.setUser("root"); dataSource.setPassword("12345678"); JdbcTemplate jdbcTemplate = new JdbcTemplate(); // 设置数据源对象,知道数据库在哪 jdbcTemplate.setDataSource(dataSource); // 执行操作 int row = jdbcTemplate.update("insert into t_user(username,password) values(?,?)", "tom11", "6000"); System.out.println(row); } }
配置数据库属性文件,数据源对象,以及jdbc模板对象
<!--加载jdbc.properties--> <context:property-placeholder location="classpath:jdbc.prpperties"/> <!--数据源对象--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <properyt name="password" value="${jdbc.password}"/> </bean> <!jdbc模板对象> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean>
spring框架核心包(6个):
- spring-aop
- spring-beans
- spring-context
- spring-core
- spring-expression
- spring-jcl
Spring JdbcTemplate基本使用步骤:
- 导入spring-jdbc和spring-tx坐标
- 创建数据库表和实体
- 创建JdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
4.执行数据操作
更新操作:
jdbcTemplate.update(sql,params)
查询操作:
jdbcTemplate.query(sql,Mapper,params)
jdbcTemplate.queryForObject(sql,Mapper,params)
1.编程式事务控制相关对象
1.1PlatformTransactionManager接口是spring的事务管理器,它里面提供了我们常用的操作事务的方法.
方法 | 说明 |
TransactionStatus getTransaction(TransactionDefination defination) | 获取事务的状态信息 |
void commit(TransactionStatus status) | 提交事务 |
void rollback(Transaction status) |
回滚事务 |
注意:
PlatformTransactionManager:是接口类型,不同的Dao层技术则有不同的实现类,例如:Dao,层技术是jdbc或mybatis时:org.springframework.jdbc.datasource.DataSourceTransactionManager
Dao层技术是hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager
1.2TransactionDefinition是事务的定义信息对象,里面有如下方法:
方法 | 说明 |
int getIsolationLevvl() | 获得事务的隔离级别 |
int getPropogationBehavior() | 获得事务的传播行为 |
int getTimeout() | 获得超时时间 |
boolean isReadOnly() | 是否只读 |
2.事务的传播行为
- REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中,一般的选择(默认值)
- SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
- MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
- REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起
- NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
- NEVER:以非事务方式运行,如果当前存在事务,抛出异常
- NESTED:如果当前存在事务,则再嵌套事务内执行.如果当前没有事务,则执行REQUIRED类似的操作
- 超时时间:默认值是-1,没有超时限制,如果有,以秒Wie单位进行设置
- 是否只读:建议查询时设置为只读
1.3TransactionStatus接口提供的是事务具体的运行状态,方法介绍如下
方法 | 说明 |
boolean hasSavepoint() | 是否存储回滚点 |
boolean isCompleted() | 事务是否完成 |
boolean isNewTransaction | 是否是新事务 |
boolean isRollbackOnly() | 事务是否回滚 |
知识要点:
- PlatformTranscatctionManager
- TransactionDefinition
- TransactionStatus
2基于xml的声明式事务控制
2.1什么是声明式事务控制
Spring的声明式四五顾明思议就是采用声明的方式来处理事务,这里所说的声明,就是指在配置文件中声明,用在spring配置文件中声明式的处理事务来代替代码式的处理事务.
声明式事务处理的作用
- 事务管理部侵入开发的组件.具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上应该如此,因为事务管理属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理 策划的话,也只需要在定义文件中重新配置即可.
注意:Spring声明式事务控制底层就是aop
2.2声明式事务控制的实现
声明式事务控制明确事项:
- 谁是切点?
- 谁是通知?
- 配置切面
事务配置:在xml文件中配置
<!--目标对象 内部的方法就是切点-->
<bean id="accountService" classs="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<!--配置平台事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!---通知 事务的增强-> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*"/> </tx:attributes> <!-配置事务的aop织入-> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl.*.*(..))"/> </aop:config> <tx:advice>
2.3切点方法的事务 参数的配置
<!--事务增强配置--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*"/> </tx:attributes> </tx:advice>
其中,<tx:method>代表切点方法的事务参数的配置.例如:
<tx:method name="transfer" isolation="REPEATABLE_READ" propggation="REQUIRED" timeout="-1" read-only="false"/>
- name:切点方法名称
- isolation:事务的隔离级别
- propogation:事务的传播行为
- timeout:超时时间
- read-only:是否只读
知识要点:
声明式事务控制的配置药店啊
- 平台事务管理器配置
- 事务通知的配置
- 事务aop织入的配置
<!--事务的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
3.2注解配置声明式事务控制解析
- 使用@Transactional在需要进行事务控制的类或时方法上修饰,注解可以用的属性同xml配置方式,例如:隔离级别,传播行为等
- 注解使用阿仔类上,name该类下的所有方法都使用同一套注解参数配置
- 使用在方法上,不同的方法可以采用不同的事务参数配置
- Xml配置文件中药开启事务的注解驱动<tx:annotation-driven/>
知识要点:
注册声明式事务控制的配置要点
- 平台事务管理器配置(xml方式)
- 事务通知的配置(@Transaction注解配置)
- 事务注解驱动的配置(tx:annotation-driven)
1.1ApplicationContext应用上下文获取方式
应用上下文对象是通过new ClassPathXMLApplicationContext(spring配置文件)方式获取的,但是每次从容器中获得Bean时都要编写new ClassPathXMLApplicationContext(Spring配置文件),
这样的弊端是配置文件加载多次,应用上下文被创建多次
在web项目中,可以使用ServletContextListener监听web应用的启动,我们可以在web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,在将其存储到最大的域ServletContext域中,这样就可以在任意位置从获得应用赏应用上下文ApplicationContext对象了
创建ApplicationContext对象的步骤:
1,.创建一个监听器的类,并继承ServletContextListener,并在contextInitializeed方法中new一个spring的容器,并把容器加入到web的servlet上下文环境中
public class ContextLoaderListener implements ServletContextListener{ public void contextInitialized(ServletContextEvent servletContextEvent){ ApplicationContext ac=new ClassPathXMLApplicationContext("ApplicationContext.xml"); //将spring的应用上下文对象存储到ServletContext域中 ServletContext servletContext=servletContextEvent.getServletContext(; servletContext.setAttribute("ac",ac); } }
2.把监听器类加入的web.xml中,让web容器在启动的时候加载这个spring的容器
<listener>
<listener-class>com.itheima.listener.ContextLoaderListener</listener-class>
</listener>
3.在其它类中调用这个spring容器获取bean.
4.简化配置:
可以把spring的配置文件ApplicationContext.xml加入到web.xml的全局参数中
4.1配置web.xml
<!--全局初始化参数--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>applicationContext.xml</param-name> </context-param>
4.2监听器中的代码
public class ContextLoaderListener implements ServletContextListener{ public void contextInitialized(ServletContextEvent servletContextEvent){ ServletContext servletContext=servletContextEven.getServletContext(); //读取web.xml中的全局参数 String contextConfiguration=servletContext.getInitParameter("contextConfigLocation"); ApplicationContext ac=new ClassPathXMLApplicationContext("contextConfiguration"); //将spring的应用上下文对象存储到ServletContext域中 ServletContext servletContext=servletContextEvent.getServletContext(); servletContext.setAttribute("ac",ac); } }
1.2Spring提供获取应用上下文的工具
上面的分析不用手动实现,Spring提供了一个监听器ContextLoaderListener就是读上述功能的封装,该监听器内部加载spring配置文件,闯将应用上下文对象,并纯粹到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils'供使用这个获取的应用上下文对象
- 在web.xml中配置ContextLoaderListener监听器(导入spring-web坐标)
2.使用WebApplicationContextUtils获得应用上下文对象ApplicationContext