Spring学习笔记
1.Spring简介
1.1Spring是什么
Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IoC
(Inverse Of Control:控制反转)和AOP
(Aspect Oriented Programming:面向切面编程)为内核。
提供了展现层SpringMVC
和持久层Spring JDBCTemplate
以及业务层事务管理
等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE企业应用开源框架。
1.2Spring优势
-
方便解耦,简化开发
通过Spring提供的IoC容器,可以将对象间的依赖关系由Spring进行控制,避免硬编码所造成的过度耦合。用户也不必再为单例模式类,属性文件解析等这些很底层的需要编写代码,可以更专注于上层的应用。
-
AOP编程的支持
通过Spring的AOP功能,方便进行面向切面编程,许多不容易易用传统OOP实现的功能可以通过AOP轻松实现。
-
声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。
-
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作。
-
方便继承各种优秀框架
Spring对各种优秀框架(Struts、Hibernate、Hessian等)的支持。
-
降低JavaEE API的使用难度
Spring对JavaEE API(如JDBC、javaMail、远程调用等)进行了薄薄的封装层,是这些API的使用难度大大降低。
-
Spring源码是经典学习范例
Spring的源代码设计精巧,结构清晰,处处体现着大师对Java设计模式灵活运用及对Java技术的高深造诣。它的源代码无疑是Java技术的最佳实践的范例。
1.3Spring的体系结构
2.Spring快速入门
2.1Spring程序开发步骤
-
导入Spring开发的基本包坐标
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
-
编写Dao接口和实现类
接口:
package com.southwind.dao; public interface UserDao { void running(); }
实现类:
package com.southwind.dao.impl; import com.southwind.dao.UserDao; public class UserDaoImpl implements UserDao { @Override public void running() { System.out.println("running"); } }
-
创建Spring核心配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userDao" class="com.southwind.dao.impl.UserDaoImpl"></bean> </beans>
-
在Spring配置文件中配置UserDaoImpl
<bean id="userDao" class="com.southwind.dao.impl.UserDaoImpl"></bean>
-
使用Spring的API获得Bean实例
package com.southwind.test; import com.southwind.dao.UserDao; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class UserTest { @Test public void runTest() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 从IoC容器中获取 UserDao userDao = context.getBean("userDao", UserDao.class); userDao.running(); } }
3.Spring配置文件
3.1Bean标签基本配置
用于配置对象交由Spring来创建
默认情况下它调用的是类中的无参构造方法
,如果没有无参构造方法则不能创建成功
基本属性:
-
id:Bean实例在Spring容器中的
唯一
标识 -
class:Bean的全限定名称
-
scope:指对象的作用范围
取值范围 说明 singleton 默认值,单例的 prototype 多例的 request web项目中,spring创建一个Bean的对象,将对象存入到request域中 session web项目中,Spring创建一个Bean的对象,将对象存入到session域中 global session web项目中,应用在Portlet环境,如果没有Portlet环境那么globalSession相当于Session -
当scope的取值为singleton时
Bean的实列个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期:
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,就一直存在
对象销毁:当应用卸载,销毁容器时,对象就被销毁了
-
当scope的取值为prototype时
Bean的实列个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean
Bean的生命周期:
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象在使用中,就一直存在
对象销毁:当对象长时间不用时,被java的垃圾回收期回收了
-
3.2Bean的生命周期
- init-method:指定类中的初始化方法名称
- destroy-method:指定类中的销毁方法名称
<bean id="userDao" class="com.southwind.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy" />
3.3Bean的实例化三种方法
-
无参构造方法实例化
无参构造方法如果不存在,将抛出异常
BeanCreationException
-
工厂静态方法实例化
<bean id="userDao" class="com.southwind.dao.StaticFactory" factory-method="getUserDao" />
工厂类
package com.southwind.dao; import com.southwind.dao.impl.UserDaoImpl; public class StaticFactory { public static UserDao getUserDao() { return new UserDaoImpl(); } }
factory-method
: 通过factory-methon属性创建对象 -
工厂实例方法实例化
-
创建类,让这个类作为工厂bean,实现接口FactoryBean
public class PersonBean implements FactoryBean<Person> { @Override public Person getObject() throws Exception { Person person = new Person(); person.setAge(21); person.setName("xin"); return person; } @Override public Class<?> getObjectType() { return Person.class; } @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } }
-
实现接口中的方法
@Nullable T getObject() throws Exception; @Nullable Class<?> getObjectType(); default boolean isSingleton() { return true; }
-
通过xml配置创建对象
<bean id="person" class="com.southwind.repository.bean.PersonBean"/>
-
测试
@Test public void personTest() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = context.getBean("person", Person.class); System.out.println(person); }
3.3Bean别名配置
name:定义bean的别名,可以定义多个,使用逗号,
分号;
空格
分隔
<bean id="userDao" name="dao dao2 dao3" class="com.southwind.dao.StaticFactory" factory-method="getUserDao" />
获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常
NoSuchBeanDefinitionException
4.Spring依赖注入
4.1setter注入
使用setter方法对属性进行注入
基本数据类型注入用value
<bean id="address" class="com.southwind.repository.Address">
<property name="city" value="南昌市" />
<property name="province" value="江西省" />
</bean>
引用数据类型注入用ref
<bean id="people" class="com.southwind.repository.People">
<property name="address" ref="address"/>
<property name="age" value="21"/>
<property name="name" value="xin"/>
</bean>
4.2构造器注入
使用constructor-arg
标签通过构造器注入
name
属性的字段要与有参构造器中形参列表中的字段一致
<bean id="people" class="com.southwind.repository.People">
<!-- <property name="address" ref="address"/>-->
<!-- <property name="age" value="21"/>-->
<!-- <property name="name" value="xin"/>-->
<constructor-arg name="address" ref="address"/>
<constructor-arg name="name" value="xin"/>
<constructor-arg name="age" value="11"/>
</bean>
根据类型对属性进行注入,使用type
属性
<bean id="people" class="com.southwind.repository.People">
<!-- <property name="address" ref="address"/>-->
<!-- <property name="age" value="21"/>-->
<!-- <property name="name" value="xin"/>-->
<!-- <constructor-arg name="address" ref="address"/>-->
<!-- <constructor-arg name="name" value="xin"/>-->
<!-- <constructor-arg name="age" value="11"/>-->
<constructor-arg type="com.southwind.repository.Address" ref="address"/>
<constructor-arg type="int" value="21"/>
<constructor-arg type="java.lang.String" value="xin"/>
</bean>
如果,形参中有相同的类型,则无法进行注入
根据参数位置进行注入,使用index
属性,从0
开始
<bean id="people" class="com.southwind.repository.People">
<!-- <property name="address" ref="address"/>-->
<!-- <property name="age" value="21"/>-->
<!-- <property name="name" value="xin"/>-->
<!-- <constructor-arg name="address" ref="address"/>-->
<!-- <constructor-arg name="name" value="xin"/>-->
<!-- <constructor-arg name="age" value="11"/>-->
<constructor-arg index="0" ref="address"/>
<constructor-arg index="1" value="21"/>
<constructor-arg index="2" value="xin"/>
</bean>
4.3p命名空间注入
基本类型:p:属性名
引用类型:p:属性名-ref
<bean id="address" class="com.southwind.repository.Address" p:city="南昌市" p:province="江西省" />
<bean id="people" class="com.southwind.repository.People" p:address-ref="address">
4.4依赖注入方式选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
5.Spring自动装配
IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程就自动装配
- 按类型(常用)
<bean id="address" class="com.southwind.repository.Address">
<constructor-arg name="City" value="南昌市"/>
<constructor-arg name="province" value="江西省"/>
</bean>
<bean id="people" class="com.southwind.repository.People" autowire="byType" />
必须要有setter方法,按类型匹配时,bean必须是唯一的
- 按名称
private Address address;
public void setAddress(String city, String province) {
}
<bean id="address" class="com.southwind.repository.Address">
<constructor-arg name="City" value="南昌市"/>
<constructor-arg name="province" value="江西省"/>
</bean>
<bean id="address1" class="com.southwind.repository.Address">
<constructor-arg name="City" value="南昌市"/>
<constructor-arg name="province" value="江西省"/>
</bean>
<bean id="people" class="com.southwind.repository.People" autowire="byName" />
通过名字匹配,bean的名称必须要与属性名
和setter方法setXxxx
一致,
依赖自动装配特征:
- 自动装配有关于引用类型依赖注入,不能对简单类型进行操作
- 使用按类型装配式(byType)必须保障容器中相同类型的bean唯一,推荐使用
- 使用按名称装配式(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
- 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
6.Spring集合注入
6.1属性注入
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
//2 数组
private String[] courses;
//2 list 集合类型属性
private List<String> list;
//3 map 集合类型属性
private Map<String,String> maps;
//4 set 集合类型属性
private Set<String> sets;
}
<bean id="student" class="com.southwind.repository.Student">
<property name="courses">
<array>
<value>java</value>
<value>数据结构</value>
</array>
</property>
<property name="list">
<list>
<value>aaaa</value>
<value>bbbb</value>
</list>
</property>
<property name="maps">
<map>
<entry key="JAVA" value="java"/>
<entry key="HP" value="hp"/>
</map>
</property>
<property name="sets">
<set>
<value>oracle</value>
<value>mysql</value>
</set>
</property>
</bean>
6.1集合注入部分提取出来
使用util
标签
public class Book {
private List<String> bookList;
}
<bean id="book" class="com.southwind.repository.Book">
<property name="bookList" ref="bookList"/>
</bean>
7.Spring引入外部文件
引入 context 名称空间
xmlns:context="http://www.springframework.org/schema/context"
创建db.properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username=root
password=admin123
从资源路径引入db.properties
<context:property-placeholder location="db.properties"/>
从文件中读取配置信息
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"/>
<property name="user" value="${username}"/>
<property name="password" value="${password}"/>
<property name="jdbcUrl" value="${url}"/>
</bean>
8.spring基于注解方式
8.1使用注解步骤
需要导入spring-aop
包,需要context约束,增加对注解的支持
开启注解支持
<context:annotation-config/>
扫描包
<context:component-scan base-package="com.wouthwinds"/>
在类上添加注解@Repository
@Component
public class Person {
public void run() {
System.out.println("人在跑");
}
}
相当于
<bean id="person" class="com.wouthwinds.repository.Person"/>
id名默认为类名,首字母小写
8.2属性注入使用注解
属性注入使用注解@Value
可以直接在属性上注入,也可以在setter方法上注入
@Value("xin")
private String name;
@Value("xin")
public void setName(String name) {
this.name = name;
}
相当于
<property name="name" value="xin" />
8.3衍生注解
@Component
有衍生注解,在web开发中,会使用mvc三层架构进行分成
- dao层:
@Respository
- service层:
@Service
- controller层:
@Controller
这四个注解功能都是一样
@Scope
用来配置bean的作用域
@Scope("singleton")
@Scope("prototype")
8.4使用注解实现自动装配
使用@AotuWired
注解,可以使用在属性上,也可以使用在setter方法上,默认是byName
使用Autowired可以不编写set方法,前提是自动装配的属性在IoC容器中存在,且符合名字
@Autowired
public void setDog(Dog dog) {
this.dog = dog;
}
public @interface Autowired {
boolean required() default true;
}
required默认为true,如果设置为false,说明这个对象可以为null,否则不允许为空
使用@Qualifier
指定bean来对属性进行注入
@Autowired
@Qualifier(value = "dog1")
public void setDog(Dog dog) {
this.dog = dog;
}
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解@Autowired完成的时候,使用@Qualifier(value=“”)去配合使用
使用@Resource
注解
@Resource是java原生的注解,可以使用在属性上,也可以使用在setter方法上
当IoC容器中的bean不唯一时,使用name
属性指定bean
@Resource(name = "dog1")
public void setDog(Dog dog) {
this.dog = dog;
}
@Resource
public void setDog(Dog dog) {
this.dog = dog;
}
@Autowired和@Resource区别
- @Autowired注解是Spring提供的,而@Resource注解是J2EE本身提供的
- @Autowird注解默认通过byType方式注入,而@Resource注解默认通过byName方式注入
- @Autowired注解注入的对象需要在IOC容器中存在,否则需要加上属性required=false,表示忽略当前要注入的bean,如果有直接注入,没有跳过,不会报错
@Nullable允许属性值为null
8.5完全注解开发
使用javaConfig配置类来代替xml配置文件
@Configurable
:代表是一个配置类,和applicationContext.xml一样
ComponentScan
扫描包下的注解
@Bean
:注册一个bean,相当于一个bean标签,注入到IoC容器中的bean的名称:类名首字母小写和方法名
@Configurable
@ComponentScan("com.southwind")
public class SouthConfig {
@Bean
public User getUser() {
return new User(); //返回值就是要注入到bean中的对象
}
}
ApplicationContext context = new AnnotationConfigApplicationContext(SouthConfig.class);
User user2 = context.getBean("getUser", User.class);
User user1 = context.getBean("user", User.class);
System.out.println(user1);
System.out.println(user2);
com.southwind.repository.User@2357d90a
com.southwind.repository.User@6328d34a
可以使用@Import
注解来导入其他配置类
@Import(Config2.class)
9.Spring AOP
9.1什么是aop
AOP是Aspect Oriented Programming,面向切面编程
,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术
AOP是OOP的延续,是软件开发的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发的效率。
作用:在优势运行期间,在不修改源码的情况下对方法进行功能增强
优势:减少重复代码,提高开发效率,并且便于维护
9.2AOP底层使用动态代理
有两种情况动态代理
-
有接口情况,使用JDK动态代理
创建接口实现类代理对象,增强类的方法
-
没有接口情况,使用cglib动态代理
创建子类的代理对象,增强类的方法
使用jdk动态代理
使用Proxy类里面的方法创建代理对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
throws IllegalArgumentException
参数1:类加载器
参数2:增强方法所在的类,这个类实现的接口,支持多个接口
参数2:实现接口InvocationHandler
,创建代理类对象,写增强的部分
Class[] interfaces = {UserDao.class};
UserDao userDao = new UserDaoImpl();
UserDao dao =
(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new ProxyUserDao(userDao));
dao.add(1,2);
实现InvocationHandler接口,必须实现invoke
方法来实现增强方法的逻辑
参数1:proxy应该是jdk自己调用的
参数2:要增强方法的名字
参数3:要增强方法的参数
把创建的是谁的代理对象,把谁传递过来*
public class ProxyUserDao implements InvocationHandler {
// 把创建的是谁的代理对象,把谁传递过来
public Object object;
public ProxyUserDao(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "方法执行了,参数是" + Arrays.toString(args));
Object res = method.invoke(object, args);
System.out.println("方法执行后" + object);
return res;
}
}
9.3AOP操作术语
-
连接点
可以被增强的方法叫连接点
-
切入点
实际被增强的方法叫切入点
-
通知(增强)
实际被增强的部分叫通知
通知的类型:
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
-
切面
动作,把通知(增强)应用到切入点的过程
9.4AOP准备
Spring框架一般都是基于AspectJ
实现AOP操作
AspectJ不是Spring组成部分,是独立的AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
基于AspectJ实现AOP操作
- 基于xml配置文件实现
- 基于注解方式实现
导入所依赖的jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
9.5切入点表达式
切入点表达式作用:知道对哪个类哪个方法进行增强
表达式格式:execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]))
举例:
execution(* com.xin.repository.UserDao.add(…))
execution(* com.xin.dao.UserDao.*(…))
execution(* com.xin.dao.*.*(…))
9.7AOP实现
9.7.1使用注解
-
创建类,在类里面定义方法
@Component public class UserDao { public void add() { System.out.println("add...."); } }
-
创建增强类(编写增强逻辑)
@Component @Aspect public class UserDaoProxy { @Before(value = "execution(* com.nix.dao.*.*(..))") public void before() { System.out.println("before......"); } }
-
进行通知配置
-
在 spring 配置文件中开启生成代理对象
<aop:aspectj-autoproxy/>
-
在增强类上面添加注解 @Aspect
@Aspect public class UserDaoProxy
-
-
配置不同类型通知
在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
@Before(value = "execution(* com.nix.dao.*.*(..))") public void before() { System.out.println("before......"); }
相同切入点抽取
使用注解@Pointcut
@Pointcut(value = "execution(* com.nix.dao.*.*(..))")
public void pointCut() {
}
@Before(value = "pointCut()")
public void before() {
System.out.println("before......");
}
有多个增强类多同一个方法进行增强,设置增强类优先级
在增强类上面添加注解 @Order(数字类型值)
,数字类型值越小优先级越高
@Order(1)
public class UserDaoP {
@Before(value = "execution(* com.nix.dao.*.*(..))")
public void before() {
System.out.println("userdaop bea");
}
}
@Aspect
@Order(3)
public class UserDaoProxy {
@Pointcut(value = "execution(* com.nix.dao.*.*(..))")
public void pointCut() {
System.out.println("pointCut");
}
@Before(value = "pointCut()")
public void before() {
System.out.println("before......");
}
}
9.7.3完全使用注解开发
使用注解@EnableAspectJAutoProxy
@Configuration
@ComponentScan(basePackages = {"com.nix"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
9.7.2配置文件
-
创建两个类,增强类和被增强类,创建方法
-
在spring配置文件中创建两个类对象
<bean id="book" class="com.nix.dao.Book"/> <bean id="bookProxy" class="com.nix.dao.BookProxy"/>
-
在spring配置文件中配置切入点
<aop:config>
// 切入点
<aop:pointcut id="p" expression="execution(* com.nix.dao.Book.buy(..))"/>
// 配置切面
<aop:aspect ref="bookProxy">
// 增强作用在具体方法
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
10.JDBCTemplate
Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作
-
引入依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.3.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.9</version> </dependency>
-
在spring配置文件中配置
dataSource
数据库连接池<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="name" value="${username}"/> <property name="password" value="${password}"/> <property name="url" value="${url}"/> <property name="driver" value="${driver}"/> </bean>
-
配置JdbcTemplate对象,注入Datasource
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean>
11.Spring事务
事务式数据库操作求基本单元,逻辑上一组操作,要么都成功,如果一个失败所有操作都失败
事务四个特性(ACID)
- 原子性
- 一致性
- 隔离性
- 持久性
11.1编程式事务控制对象
PlatformTransactionManager
platformTransactionManager
接口式spring的事务管理器,它里面提供了我们常用的操作事务的方法
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
获取事务的状态信息
void commit(TransactionStatus var1) throws TransactionException;
提交事务
void rollback(TransactionStatus var1) throws TransactionException;
回滚事务
注意:
PlatformTransactionManager式接口类型,不同的Dao层则有不同的实现类,例如:Dao层技术式jdbc或mybatis时:org.springframework.jdbc.datasource.DataSourceTransactionManager,Dao层式hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager
TransactionDefinition
TransactionDefinition
是事务的定义信息对象
int getIsolationLevel();
获取事务的隔离级别
int getPropogationBehavior();
获取事务的传播行为
int getTimeout();
获取超时时间
boolean isReadOnly();
是否只读
事务隔离级别
设置隔离级别,可以解决事务并发产生的问题,如脏读,不可重复读和虚读
- ISOLATION_DEFAULT
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIZABLE
事务传播行为
- REQUIERD:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,就如到这个事务中
- SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
- MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
- REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起
- NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
- NEVER:以非事务方式运行,如果当前存在事务,就抛出异常
- NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作
- 超时时间:默认值是-1,没有超时限制,如果有,以秒为单位进行设置
- 是否只读:建议查询时设置为只读
TransactionStatus
TransactionStatus
接口提供的是事务具体的运行状态
boolean hasSavepoint();
是否存储回滚点
boolean isCompleted();
事务是否完成
boolean isNewTransaction();
是否是新事物
boolean isRollbackOnly();
事务是否回滚
11.2基于xml的声明式控制
spring的声明式事务顾名思义就是采用声明的方式来处理事务
,这里所说的声明,就是旨在配置文件中声明,用在spring配置文件中声明式的处理事务来代替代码式的处理事务
声明式事务处理的作用
- 事务管理不侵入开发的组件。具体来说,业务逻辑对象不会意识到正在事务管理之中,事实上应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可。
- 在不需要事务管理的时候,只要在设定文件上修改一下,即可一区事务管理服务,无需改变代码重新编译,这样维护起来极其方便。
spring声明式事务控制底层就是AOP
目标对象,内部的方法就是切点
配置平台事务管理器transactionManager
<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>
</tx:advice>
其中,<tx:method>代表切点方法的事务参数的配置
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timout="-1" read-only="false"/>
- name:切点方法名称
- isolation:事务的隔离级别
- propogation:事务的传播行为
- timeout:超时时间
- read-only:是否只读
配置事务的aop织入
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.nix.dao.*.*(..))"/>
</aop:config>
11.3基于注解
开启事务的注解驱动
<tx:annotation-driven transaction-manager="transactionManager"/>
在类或增强的方法添加@Transactional
@Transactional(isolation=Isolation.READ_COMMITTED,propagation=Propagation.REQUIRED)
public void transfer() {
}