Spring是什么?
Spring是于2003年兴起的一个轻量级的,IOC和AOP的Java开发框架,它是为了简化企业级应用开发而生的
优点
轻量级的 Spring框架使用的jar都比较小,一般在1M以下或者几百kb。
Spring核心功能所需的jar总在3M左右。
Spring框架运行占用的资源很小,运行效率高。
非侵入式的 UserSrlevt extends HttpServlet(侵入式)
编写一些业务类的时候不需要继承Spring特定的类,通过配置完成依赖注入后就可以使用,这样spring就没有入侵到我们的业务代码中
IOC
即InversionofControl,缩写为IOC,就是由SpringIoC容器管理对象,而非传统实现中由程序代码直接操控.
AOP
直译过来就是面向切面编程。AOP是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面.
一站式框架
Spring本身也提供了数据访问功能和web功能,以及可以很好的管理其他框架
Spring体系结构
CoreContainer(核心容器):
Beans:管理Beans
Core:Spring核心
Context:配置文件
ExpressionLanguage:SpEL表达式
AOP(切面编程)
AOP框架:Aspects
DataAccess(数据库整合):
JDBC,ORM,OXM,JMS,Transaction
Web(MVCWeb开发):
Web,Servlet,Portlet,Struts
Test(Junit整合)
官网地址:Spring | Home
Spring搭建
Maven导入spring核心基础jar
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
编写spring配置文件
<!-- spring.xml文件 -->
<?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">
<!--
把需要spring管理的对象配置进行
-->
<bean id="admin" class="com.ffyc.spring.model.Admin"></bean>
</beans>
编写实体类
public class Admin {
private int id;
private String account;
public Admin() {
/*每次创建对象会调用无参构造方法*/
System.out.println("Admin无参构造方法");
}
public Admin(int id, String account) {
this.id = id;
this.account = account;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
@Override
public String toString() {
return "Admin{" +
"id=" + id +
", account='" + account + '\'' +
'}';
}
}
测试spring
public static void main(String[] args) {
/*
读取配置文件,生成xml文件配置的类的对象
ApplicationContext 是Spring的一个底层接口,定义一些规范
ClassPathXmlApplicationContext 是Spring的一个具体的落地实现类,创建并管理对象 里面的参数是配置文件
*/
ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
//IOC控制反转.将生成对象的权利反转给spring框架,在哪儿需要,在哪儿注入
/*
//默认创建一个单例对象
Admin admin = app.getBean("admin", Admin.class);
// 通过别名创建对象
Admin admin1 = app.getBean("admin", Admin.class);
System.out.println(admin==admin1);//true
*/
//创建对象默认调用无参构造
Admin admin = app.getBean("admin", Admin.class);
System.out.println(admin);
}
Spring IOC
IOC(控制反转)
读作“反转控制”(InverseofControl)更好理解,不是什么技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理
IOC容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象的整个生命周期都是由容器来控制。我们需要使用的对象都由ioc容器进行管理,不需要我们再去手动通过new的方式去创建对象,由ioc容器直接帮我们组装好,当我们需要使用的时候直接从ioc容器中直接获取就可以了
正控
若要使用某个对象,需要自己去负责对象的创建
反控
若要使用某个对象,只需要从spring容器中获取需要使用的对象,不关心对象创建的过程,把创建对象的控制权反转给spring框架。
IOC目的
降低耦合度
底层实现方式
解析xml/扫描注解标签 + 工厂模式 + 反射机制
SpringBean管理
基于xml配置方式
bean配置需要spring管理的类
id生成的对象名
class 全类名
name 对象别名,可以为多个
scope:
singleton(默认值):在 Spring 中只存在一个 bean 实例, 单例模式.
prototype:原型 getBean()的时候都会 new Bean()
request:每次 http 请求都会创建一个 bean, 仅用于 WebApplicationContext 环境
session:同一个 http session 共享一个 Bean, 不同 Session 使用不同的 Bean, 使用环境同上
<!--配置我们项目中的类,配置类之后Spring就会对对象进行对象的存储管理(生成对象存储)
由Spring框架生成的对象称之为一个bean,特指Spring框架创建的对象,会给一定特殊功能
id:生成对象的表示
class:类的地址(全类名)
name:对象别名,通过name也可以获取对象
scope:范围,作用域
singleton:单例的,整个应用程序中只创建一次,多次获取是同一个,在Spring容器启动时就创建
prototype:原型的(多例的) 每次获取时,会创建一个新的对象 -->
<bean id="admin" name="admin1,admin2" class="com.ffyc.spring.model.Admin" scope="prototype"></bean>
xml配置方式依赖注入
DI:Dependency Injection(xml配置方式依赖注入)
指Spring创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设置给该对象。
实现IOC需要DI注入
有两种注入方式
1、构造方法注入
2、set方法注入
构造方法注入
<!--通过属性名注入值-->
<bean id="admin" class="com.ffyc.spring.model.Admin">
<constructor-arg name="id" value="100"></constructor-arg>
<constructor-arg name="account" value="admin"></constructor-arg>
</bean>
<!--通过属性的类型注入值-->
<bean id="admin" class="com.ffyc.spring.model.Admin">
<constructor-arg type="java.lang.Integer" value="100"></constructor-arg>
<constructor-arg type="java.lang.String" value="admin"></constructor-arg>
</bean>
set方法注入
<bean id="admin" class="com.ffyc.spring.model.Admin">
<property name="id" value="1"></property>
<property name="account" value="admin"></property>
</bean>
<!-- spring管理了 adminDao adminService-->
<bean id="adminDao" class="com.ffyc.spring.dao.AdminDao"></bean>
<bean id="adminService" class="com.ffyc.spring.service.AdminService">
<property name="adminDao" ref="adminDao"></property>
</bean>
注解方式实现
注解开发准备工作
导入注解需要的jar包
注解需要的jar包封装在spring aop jar 包中
开启注解扫描
在spring的配置文件中开始注解扫描
<!--
开启spring注解扫描
<context:component-scanbase-package="包名"></context:component-scan>
-->
<context:component-scan base-package="com.ffyc.spring"></context:component-scan>
注解创建对象
@Component
@Service
@Repository
以上注解都可以实现创建对象的功能,知识为了后续扩展功能,在不同的层使用不同的注解标记
创建原型或者单例
@Scope(value = “prototype”) 原型
@Scope(value = “singleton”) 单例
@Component(value = "admin") //想当于<bean id=“adminadmin” class=“”></bean>
@Scope(value = "singleton") //指定生成对象的策略(单例)
public class Admin
@Service(value = "adminService")
public class AdminService
@Repository(value = "adminDao")
@Scope(value = "singleton") //指定生成对象的策略(单例)
public class AdminDao
注解方式注入属性
@Autowired
@Autowired 是 Spring 提供的注解,可以写在字段和 setter 方法上。如果写在字段上,那么就不需要再写 setter 方法。默认情况下它要求依赖对象必须存在, 如果允许 null 值,可以设置它的 required 属性为 false。
byType 自动注入
该注解默认使用按类型自动装配 Bean 的方式
byName 自动注入
如果我们想使用按照名称(byName)来装配,可以结合@Qualifier 注解一起使用。
需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的 value 属性用于指定要匹配的Bean 的 id 值
/*
@Autowired 是spring框架自身提供的注解标签
required = true 这是默认的 注入的时候不能为null值
是根据属性的类型自动注入(根据属性的类型在spring容器中查找)
也可以通过对象名查找注入,需要结合@Qualifier(value = "adminDao")
*/
@Autowired(required = false)
@Qualifier(value = "adminDao")
AdminDao adminDao;
JDK 注解@Resource 自动注入
Spring 提供了对 jdk 中@Resource 注解的支持。@Resource 注解既可以按名称匹配 Bean,也可以按类型匹配 Bean。默认按照 ByName 自动注入
byName 注入引用类型属性
@Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean 的 id
//指定注入的对象名,不写就根据类型查找
@Resource(name = "adminDao") //是JDK自身提供的注解标签,也支持byName和byType两种注入方式
AdminDao adminDao;
注解与XML的对比
注解优点
方便,直观,高效(代码少,没有配置文件的书写那么复杂)
注解缺点
以硬编码的方式写入到Java代码中,修改是需要重新编译代码的
xml优点是
配置和代码是分离的,在xml中做修改,无需编译代码,只需重启服务器即可将新的配置加载
xml的缺点是
编写麻烦,效率低,大型项目过于复杂
SpringJDBC
Spring是个一站式框架:Spring自身也提供了控制层的SpringMVC和持久层的SpringJdbcTemplate
开发步骤
下载Spring Jdbc Template的jar包
<!--spring-jdbc
spring数据访问层功能,
提供Jdbctemplate封装的方法操作数据库
主要使用的是其中的事务管理功能
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!--阿里数据源
阿里巴巴开源的数据源管理组件音译的德鲁伊
提供与数据库连接实现,还提供数据库连接池功能
数据库连接池因为频繁创建销毁数据库连接对象(Connection)
开销较大,提出池的概念
事先缓存一部分连接对象,使用时直接从池中获取
用完后不销毁,还回到池中,减少创建销毁的时间开销
-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
导入属性文件
<context:property-placeholder location = "config.properties"></context:property-placeholder>
管理数据源对象
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driverName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${pword}"></property>
<property name="initialSize" value="${initialSize}"></property>
<property name="maxWait" value="${maxWait}"></property>
<property name="maxActive" value="${maxActive}"></property>
</bean>
在配置文件中创建JdbcTemplate
<!-- 配置Spring jdbcTemplate 提供了操作方法 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
在类中获得JdbcTemplate对象,就可以直接使用
@Autowired
JdbcTemplate jdbcTemplate;
JdbcTemplate中常用的方法
execute:无返回值,可执行ddl,增删改语句
update:执行新增、修改、删除语句
queryForXXX:执行查询相关语句
操作
插入
jdbcTemplate.update(
"insert into admin(account,password,gender)
values(?,?,?)","zxc","123","男");
创建表
jdbcTemplate.execute("create table test(id int)");
查询
int count = jdbcTemplate.queryForObject("select count(*) from admin", Integer.class);
查询返回对象的集合
List<Admin> list = jdbcTemplate.query("select * from admin", new RowMapper<Admin>() {
@Override
public Admin mapRow(ResultSet resultSet, int i) throws SQLException {
Admin admin = new Admin();
admin.setId(resultSet.getInt("id"));
admin.setAccount(resultSet.getString("account"));
admin.setPassword(resultSet.getString("password"));
admin.setGender(resultSet.getString("gender"));
return admin;
}
});
System.out.println(list);
AOP概述
AOP (Aspect Oriented Programming) 面向切面编程
通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
AOP是OOP(面向整体设计)的延续。
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发效率。
OOP
OOP (面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
AOP
针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果
AOP的好处
减少重复,专注业务
注意:面向切面编程只是面向对象编程的一种补充
核心思想
使用动态代理的方式,在方法执行前后,或者出现异常时加入某种逻辑
可以实现在不修改代码的情况下,为程序添加新的功能
抽取的代码有条件(功能与业务逻辑没有直接关系)
使用案例
事务处理:开启事务,关闭事务,出现异常后回滚事务
权限判断:在执行方法前,判断是否具有权限
日志:在执行前进行日志处理
@Repository(value = "adminDao")
@Scope(value = "singleton") //指定生成对象的策略(单例)
public class AdminDao {
@Autowired
JdbcTemplate jdbcTemplate;
/*
saveAdmin , updateAdmin这些方法,都可以被增强(添加其他功能),称为连接点
saveAdmin实际被增强了,那么saveAdmin被称为切入点
*/
public void saveAdmin() {
System.out.println("保存管理员");
}
}
public class CommonUtil {
/*
目标:连接点,切入点所在的类,实际执行着
切面:整个过程
代理:为目标类创建的代理对象
通知 实际要增强的功能
*/
//@Before("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") //前置通知
@After("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") // 后置通知
public void saveLog(){
System.out.println("保存日志");
}
}
AOP的基本概念
连接点(Joinpoint):类中可以被增强的方法,这个方法就被称为连接点
切入点(pointcut):类中有很多方法可以被增强,但实际中只有add和update被增了,那么add和update方法就被称为切入点(实际实现的连接点)
@Repository(value = "adminDao")
@Scope(value = "singleton") //指定生成对象的策略(单例)
public class AdminDao {
@Autowired
JdbcTemplate jdbcTemplate;
/*
saveAdmin , updateAdmin这些方法,都可以被增强(添加其他功能),称为连接点
saveAdmin实际被增强了,那么saveAdmin被称为切入点
*/
public void saveAdmin() {
System.out.println("保存管理员");
}
}
通知(Advice):通知是指一个切面在特定的连接点要做的事情(增强的功能)。通知分为方法执行前通知,方法执行后通知,环绕通知等.
切面(Aspect):把通知添加到切入点的整个过程称为切面.
public class CommonUtil {
/*
目标:连接点,切入点所在的类,实际执行着
切面:整个过程
代理:为目标类创建的代理对象
通知 实际要增强的功能
*/
//@Before("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") //前置通知
@After("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") // 后置通知
public void saveLog(){
System.out.println("保存日志");
}
}
目标(Target):代理的目标对象(连接点,切入点所在类)
public class AdminDao{
}
代理(Proxy):向目标对象应用通知时创建的代理对象
springAOP实现
对于AOP这种编程思想,很多框架都进行了实现。spring就是其中之一,可以完成面向切面编程。
AspectJ 也实现了 AOP 的功能,AspectJ 是一个基于 Java 语言的 AOP 框架,它提供了强大的 AOP 功能,且其实现方式更为简捷,使用更为方便, 而且还支持注解式开发。所以,Spring 又将 AspectJ 的对于 AOP 的实现也引入到了自己的框架中。
在 Spring 中使用 AOP 开发时,一般使用 AspectJ 的实现方式。
AspectJ 中常用的通知有五种类型:
前置通知,后置通知,环绕通知,异常通知,最终通知
下载AOP相关jar
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
基于aspectj的xml配置方式实现
<!-- 让spring管理增强功能的类 -->
<bean id="commonUtil" class="com.ffyc.spring.util.CommonUtil"></bean>
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut id="saveAdmin" expression="execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))"/>
<aop:aspect ref="commonUtil">
<aop:before method="saveLog" pointcut-ref="saveAdmin"></aop:before>
<aop:after method="saveLog" pointcut-ref="saveAdmin"></aop:after>
<aop:after-throwing method="exception" pointcut-ref="saveAdmin" throwing="e"></aop:after-throwing>
<aop:around method="around" pointcut-ref="saveAdmin"></aop:around>
</aop:aspect>
</aop:config>
public class CommonUtil {
/*
目标:连接点,切入点所在的类,实际执行着
切面:整个过程
代理:为目标类创建的代理对象
通知 实际要增强的功能
*/
//@Before("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") //前置通知
@After("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") // 后置通知
public void saveLog(){
System.out.println("保存日志");
}
}
/*
通知:在连接点上要做的事情(增强的功能)
通知时又可以分为前置通知、后置通知、环绕通知、异常通知
*/
public void saveLog(){
System.out.println("保存日志");
}
基于注解方式的实现
在spring配置文件中
启动 AspectJ 支持:<aop:aspectj-autoproxy />
<!--开启自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Component
@Aspect
public class CommonUtil {
/*
目标:连接点,切入点所在的类,实际执行着
切面:整个过程
代理:为目标类创建的代理对象
通知 实际要增强的功能
*/
//@Before("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") //前置通知
@After("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))") // 后置通知
public void saveLog(){
System.out.println("保存日志");
}
@AfterThrowing(value = "execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))",throwing = "e") // 异常通知
public void exception(Throwable e) {
System.out.println(e.getMessage());
}
@Around("execution(* com.ffyc.spring.dao.AdminDao.saveAdmin(..))")
public void around(ProceedingJoinPoint joinPoint){
System.out.println("之前开启事务");
try {
joinPoint.proceed();//调用切入点方法
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println(throwable.getMessage());//异常通知
}
System.out.println("之后提交事务");
}
}
Spring事物管理
事物可以看做是由对数据库若干操作组成的一个单元。
我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作 的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常, 异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操作数据的并不可靠,需要在这种情况下进行回退。
事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求
Spring 中的事务管理分为两种形式,一种是编程式事务,一种是声明式事务
编程式事务
在项目中很少使用,这种方式需要注入一个事务管理对象TransactionTemplate,然后在我们代码中需要提交事务或回滚事务时自己写代码实现
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
TransactionTemplate t; //编程式事务,在我们的代码中需要句mybatis那样手动(显示)的提交回滚事务
/*
事务:数据库事务是对数据库若干操作组成的一个单元(整体)
在我们的一次save时,里面包含了两个或者更多个对数据库的操作
那么我们认为这若干个操作应该是一个单元(整体)
这就是事务的原子性(不可分割性),多个操作要么都执行成功,要么都不执行
*/
public void save1(){
//t.execute(""); 使用t的方法实现编程式事物
jdbcTemplate.update("insert into admin(account,password,sex)values(?,?,?)","jim1","111","男");
int a = 10/0;
jdbcTemplate.update("insert into admin(account,password,sex)values(?,?,?)","jim2","111","男");
}
声明式事务
声明式事务管理建立在 AOP 基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的
Spring 声明式事物管理方式有两种:
基于 xml 配置
基于注解实现
Spring 事物管理 APIPlatformTransactionManager 事物管理器接口
Spring 针对不同的 dao 框架,提供了不同的实现类,Jdbc,mybatis 事物管理实现类是 DataSourceTransactionManager
配置事物管理器
<!-- 配置 spring 事务管理类, 并注入数据源 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
注解方式
<!--注解方式实现事务管理配置-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
在service中控制事务
@Service(value="userservice")
@Transactional
声明式事务不生效的场景
1.修饰一个非public方法,会导致事务失效
2.方法中出现异常,被try catch捕获了认为方法没有出现异常,事务正常提交
//这里的异常被捕获后,在调用处等于没有异常
@Transactional(propagation = Propagation.REQUIRED)
public void savelog(){
commonDao.save();
try{
int a = 10/0;
}catch (Exception e){
}
}
3.默认情况下出现编译期异常,会导致事务失效,rollbackFor = Exception.class 任何异常都不提交事务
4.@Transactional事务传播行为设置错误
5.数据库引擎不支持事务,mysql中只有InnoDB引擎支持事务
// 不使用public 默认使用default @Transactional就会失效,此方法就没有事务了
@Transactional (propagation = Propagation.REQUIRED)
void save(){
deptDao.save();
commonService.savelog();
}
6.在同一个类中的一个非事务方法中,通过this调用事务方法,此时是通过非代理对象调用的,导致事务失效
Spring事务传播行为
什么叫事务传播行为:
即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。事务传播行为是 Spring 框架独有的事务增强特性,他不属于的事务实际提供方数据库行为
事务传播行为是 Spring 框架独有的事务增强特性,他不属于的事务实际提供方数据库行为
例如:methodA 事务方法调用 methodB 事务方法时,methodB 是继续在调用者 methodA 的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB 的事务传播行为决定的
spring定义了七种传播行为
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务,加入到这个事务中,这是最常见的 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务 挂起 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事 |
@Service
public class LogService {
@Autowired
LogDao logDao;
/*
REQUIRED 当一个有事务的方法,调用了传播行为为REQUIRED的方法,那么被调用的方法会合并到调用它的方法事务中
没有事务的方法,调用了传播行为为REQUIRED的方法,那么被调用的方法会自己开启一个事务执行
SUPPORTS 当一个有事务的方法,调用了传播行为为SUPPORTS,那么被调用的方法会合并到调用它的方法事务中
当一个有事务的方法,调用了传播行为为SUPPORTS,那么被调用的方法也就没有事务
REQUIRES_NEl 无论调用的方法中,是否有事务,此方法都会创建一个独立的新的事务
*/
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void saveLog(){
logDao.saveLog();
}
}
Spring集成Mybatis
Spring 集成 Mybatis 其核心是将 SqlSessionFactory 交由 Spring 管理,并由 Spring 管理对 dao 接口的代理实现。
spring 项目的搭建和mubatis的搭建和之前一样
导入 mybatis jar 包
<!--spring-mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
添加相关配置文件
在spring_mybatis里面配置 sqlSessionFactory 并生成接口代理
<!--spring管理生成sqlSessionFactory读取mybatis各项配置文件-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybaitsConfig.xml"></property>
<property name="mapperLocations" value="classpath:mappers/*Mapper.xml"></property>
</bean>
<!--指定包下面的接口代理对象-->
<bean id="mapperFactory"
class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ffyc.ssm.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
在service中注入dao代理接口,此借口由spring代理实现
@Service(value = "loginService")
public class LoginService {
@Autowired
LoginDao loginDao;
public Admin login(Admin admin){
return loginDao.login(admin);
}
}