建设企业银行网站多少,做汽车团购网站,海报设计兼职app,个性化网站成功的案例spring是于2003年兴起的一款轻量级的#xff0c;非侵入式的IOC和AOP的一站式的java开发框架#xff0c;为简化企业级应用开发而生。 轻量级的#xff1a;指的是spring核心功能的jar包不大。 非侵入式的#xff1a;业务代码不需要继承或实现spring中任何的类或接口 IOC…spring是于2003年兴起的一款轻量级的非侵入式的IOC和AOP的一站式的java开发框架为简化企业级应用开发而生。 轻量级的指的是spring核心功能的jar包不大。 非侵入式的业务代码不需要继承或实现spring中任何的类或接口 IOC控制反转Inverse of Control以前项目都是在哪儿用到对象在哪儿new把生成对象的权利反转给spring框架让spring把对象管理起来在哪用在哪注入 AOP面向切面编程。AOP 是一种编程思想是面向对象编程OOP的一种补充。面向对象编程将程序抽象成各个层次的对象而面向切面编程是将程序抽象成各个切面。 一站式框架
提供核心功能主要是IOC创建管理对象提供面向切面编程增强程序扩展对数据访问层进行了封装(重点在于事务管理)对web层进行封装使得请求更加便捷
Spring Hello World搭建
1.Maven 导入 spring 核心基础 jar
!-- spring-context --
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.2.RELEASE/version
/dependency2.编写一个Admin实体类
package com.ffyc.ssm.model;public class Admin {private Integer id;private String account;public Admin() {System.out.println(admin无参构造);}public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getAccount() {return account;}public void setAccount(String account) {this.account account;}
}3.编写 spring 配置文件在resources/spring.xml中
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd!--配置需要让spring进行管理的类--bean idadmin classcom.ffyc.ssm.model.Admin/bean
/beans4.测试spring 读取spring配置文件并对文件中配置的对象进行创建
package com.ffyc.ssm.test;public class Test1 {public static void main(String[] args) {/*以前使用对象方式,在哪儿用,在哪儿newnew Admin();spring思想是,由框架统一对项目中的类进行管理(创建对象,后期增强一些功能),在需要的地方注入即可*///Map(admin,new Admin)//ClassPathXmlApplicationContext就是spring中的实际实现者ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);//Object adminapp.getBean(admin);//不知道返回的类型,从Map中拿出new Admin对象Admin adminapp.getBean(admin,Admin.class);//明确类型System.out.println(admin);}
}IOC(控制反转)
正控若要使用某个对象需要自己去负责对象的创建 反控若要使用某个对象只需要从 Spring 容器中获取需要使用的对象不关心对象的创建过程也就是把创建对象的控制权反转给了 Spring 框架 **底层实现方式**解析 xml/扫描注解标签 工厂模式 反射机制
Spring Bean 管理
1、基于 xml 配置方式
配置需要让spring进行管理的类 id“唯一的标识” class“让spring管理的类名” bean对象由spring框架创建并管理的对象
Scope“singleton 默认值”单例的在整个应用程序中只创建一个对象在spring框架启动时就创建好了scope“prototype”原型的每次获取时创建一个对象可以创建多个
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd!--配置需要让spring进行管理的类--bean idadmin classcom.ffyc.ssm.model.Admin scopeprototype/bean
/beanspublic class Test1 {public static void main(String[] args) {//读取spring配置文件,并对文件中配置的对象进行创建//ClassPathXmlApplicationContext就是spring中的实际实现者ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);Admin admin1app.getBean(admin,Admin.class);System.out.println(admin);System.out.println(admin1);}
}
/*
admin无参构造
admin无参构造
com.ffyc.ssm.model.Admin685cb137
com.ffyc.ssm.model.Admin6a41eaa2
*/spring框架创建对象控制反转时为对象的属性进行赋值操作这个赋值操作称为依赖注入 1.属性赋值 getXXX、setXXX方法
bean idadmin classcom.ffyc.ssm.model.Admin scopeprototypeproperty nameid value10/propertyproperty nameaccount value张三/property
/beanpublic class Test1 {public static void main(String[] args) {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);System.out.println(admin);}
}
/*
admin无参构造
Admin{id10, account张三}
*/2.构造方法赋值
bean idadmin classcom.ffyc.ssm.model.Admin scopeprototypeconstructor-arg nameid value1/constructor-argconstructor-arg nameaccount value1/constructor-arg
/beanpublic class Test1 {public static void main(String[] args) {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);System.out.println(admin);}
}
//Admin{id1, account1}在一个方法中注入另一个方法
bean idadmin classcom.ffyc.ssm.model.Admin scopeprototypeconstructor-arg nameid value1/constructor-argconstructor-arg nameaccount value1/constructor-arg
/bean
bean idadminDao classcom.ffyc.ssm.dao.AdminDao/bean
bean idadminService classcom.ffyc.ssm.service.AdminServiceproperty nameadminDao refadminDao/property !--在adminService中注入adminDao--
/beanpublic class Test2 {public static void main(String[] args) {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);AdminService adminServiceapp.getBean(adminService,AdminService.class);adminService.save(admin);}
}2、注解方式实现建议
1、注解需要的jar包 注解功能封装在AOP包中导入 Spring aop jar 包即可
!-- spring-context --
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.2.RELEASE/version
/dependency2、开启注解扫描
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!--开启注解扫描,包名范围尽可能大一些--context:component-scan base-packagecom.ffyc.ssm /context:component-scan
/beans3、注解创建对象 有注解标签才是spring管理的对象并创建对象 1.Component(value “admin”) 一般用于模型类等同于 2.Scope(value“prototype”) 原型(多次) Scope(value“singleton”) 单例(一次)
Component(value admin)
Scope(value singleton)3.Repository(value “adminDao”)用于dao层
Repository(value adminDao)
public class AdminDao {public void saveAdmin(Admin admin){System.out.println(保存管理员admin);}
}4.Service(value “adminService”) 5.Autowiredspring框架提供的一种自动注入的注解标签可以写在字段和 setter 方法上。如果写在字段上那么就不需要再写 setter 方法。默认情况下它要求依赖对象必须存在如果允许 null 值可以设置它的 required 属性为 false。 有两种方式去查找对象:
byType去spring容器中根据当前类型搜索AutowiredbyName通过名称查找需要结合 Qualifier(value“adminDao”)value值和Repository(value “adminDao”)里面的value对应 6.Resource是jdk中提供的一个注解标签byType去spring器中根据当前类型搜索ResourcebyName通过名称查找,Resource(name “adminDao”) Autowired(requiredtrue)注入时对象值不能为空为空报错
Service(value adminService)
public class AdminService {/*AutowiredQualifier(value adminDao)AdminDao adminDao;//依赖注入*///ResourceResource(name adminDao)AdminDao adminDao;public void save(Admin admin){adminDao.saveAdmin(admin);}
}public class Test3 {public static void main(String[] args) {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);AdminService adminServiceapp.getBean(adminService,AdminService.class);adminService.save(admin);}
}3、注解与 XML 的对比
注解优点 方便、直观、高效代码少没有配置文件的书写那么复杂。 **注解缺点**以硬编码的方式写入到 Java 代码中修改是需要重新编译代码的通过maven把项目重新编译compile一下。 xml 优点是 配置和代码是分离的在 xml 中做修改无需编译代码只需重启服务器即可将新的配置加载。 **xml 缺点是**编写麻烦效率低大型项目过于复杂。
Spring JDBC
spring框架中的JDBC功能
jdbc封装: JdbcTemplate(了解即可 后面常用mybatis)事务管理(重点)ioc实际的应用 Spring 是个一站式框架Spring 自身也提供了控制层的 SpringMVC 和 持久层的 Spring JdbcTemplate。 1.下载 Spring JdbcTemplate 的 jar 包 导入jdbc模块依赖
!-- spring-jdbc --
dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.2.2.RELEASE/version
/dependency导入mysql
!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --
dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.16/version
/dependency导入阿里巴巴提供的数据源管理组件数据源组件封装了连接数据库还有数据库连接池功能 druid(德鲁伊)常用的数据库链接池组件dbcp、c3p0
!-- 阿里的数据源 --
dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.10/version
/dependency2.config.properties
classDriverNamecom.mysql.cj.jdbc.Driver
urljdbc:mysql://127.0.0.1:3306/ssmdb?serverTimezoneAsia/Shanghai
unameroot
pwd1234563.db.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!--配置jdbc功能--!--负责加载config.properties文件--context:property-placeholder locationclasspath:config.properties/context:property-placeholder!--spring统一管理数据库链接对象,创建对象并赋值--bean iddataSource classcom.alibaba.druid.pool.DruidDataSourceproperty namedriverClassName value${classDriverName}/propertyproperty nameurl value${url}/propertyproperty nameusername value${uname}/propertyproperty namepassword value${pwd}/propertyproperty nameinitialSize value5/propertyproperty namemaxActive value10/property/bean!--创建spring框架封装的jdbc功能的实现类--bean idjdbcTemplate classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property !--注入数据源对象--/bean!--以后引入mybatis需要数据源对象直接注入即可--
/beans4.spring.xml注解db.xml
import resourceclasspath:db.xml/import !--指的是target/classes下的--增删改用update
Repository(value adminDao)
public class AdminDao {AutowiredJdbcTemplate jdbcTemplate;public void saveAdmin(Admin admin){//jdbcTemplate.update(insert into admin(account,password)value(?,?),aaa,111);jdbcTemplate.update(delete from admin where id ?,5);}
}查询返回单个结果
public void saveAdmin(Admin admin){Admin admin2jdbcTemplate.queryForObject(select * from admin where id?,new RowMapperAdmin() {Overridepublic Admin mapRow(ResultSet resultSet, int i) throws SQLException {Admin admin1new Admin();admin1.setId(resultSet.getInt(id));admin1.setAccount(resultSet.getString(account));return admin1;}},1);System.out.println(admin2);
}查询返回多个结果
public void saveAdmin(Admin admin){ListAdmin adminListjdbcTemplate.query(select * from admin,new RowMapperAdmin() {Overridepublic Admin mapRow(ResultSet resultSet, int i) throws SQLException {Admin admin1new Admin();admin1.setId(resultSet.getInt(id));admin1.setAccount(resultSet.getString(account));return admin1;}});System.out.println(adminList);
}AOP
不使用 AOP 的开发方式
案例 先定义好接口与一个实现类该实现类中除了要实现接口中的方法外还要写两个非业务方法。非业务方法也称为交叉业务逻辑
doTransaction()用于事务处理doLog()用于日志处理 然后再使接口方法调用它们。接口方法也称为主业务逻辑. 在方法中想要实现额外功能时,需要在业务代码中显示调用. 即使抽取一个工具类,将这些方法封装起来,依然还是需要显示调用.
AOP概述
AOP 为 Aspect Oriented Programming 的缩写意为面向切面编程AOP 可以**对业务逻辑和非业务逻辑进行隔离从而使得各部分之间的耦合度降低提高程序的可重用性**同时提高了开发的效率。将程序中的一些非业务代码进行提取在不需要修改原来代码的情况下为程序添加额外的功能。 AOP思想不是spring框架特有的只是spring框架引入使用了这一思想。 面向切面编程的好处就是: 减少重复,专注业务 注意面向切面编程只是面向对象编程的一种补充。 核心原理 使用动态代理的方式在执行方法前后或者出现异常的时候做加入相关的逻辑. 非业务代码使用案例:
事务处理开启事务关闭事务出现异常后回滚事务验证权限在执行方法前判断是否具有权限打印日志在执行前进行日志处统一异常处理
是怎么做到的底层实现使用的是动态代理模式。是通过一个代理对象来实现对非业务代码进行调用的。告诉代理对象调用哪个方法时让代理对象去帮助我们调用哪个方法 代理对象(4s 中介 手机店)
AOP的基本概念
**连接点Joinpoint**类中可以被增强的方法 **切入点pointcut**类中有很多方法可以被增强但实际中只有 add 和 update被增了那么 add 和 update 方法就被称为切入点类中实际被增强的方法 通知Advice 指提取的非业务的功能。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知 **切面Aspect**把通知添加到切入点的整个过程 目标Target 代理的目标对象(连接点,切入点所在类AdminDao) 代理Proxy 向目标对象应用通知时创建的代理对象
springAOP实现
有两种实现方式1.xml配置方式 2.注解方式
1、xml配置方式
对于 AOP 这种编程思想很多框架都进行了实现。Spring 就是其中之一可以完成面向切面编程。 AspectJ 是一个基于 Java 语言的 AOP 框架它提供了强大的 AOP 功能且其实现方式更为简捷使用更为方便 而且还支持注解式开发。所以spring中引入了一个AspectJ的aop框架. 下载 AOP 相关 jar
dependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion5.2.2.RELEASE/version
/dependency!--spring.xml中--
import resourceclasspath:aopDemo.xml/import基于 aspectj 的 xml 配置方式实现。 先把类交给spring管理这样spring生成的代理对象才可以调用
!--aopDemo.xml中--
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd!--把非业务代码(通知) 交给spring框架管理,以后要用到这个类的方法,就把myutil注入--bean idmyutil classcom.ffyc.ssm.util.MyUtil/beanaop:config!--配置切入点--aop:pointcut idsaveAdmin expressionexecution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..))/!--将通知与切入点进行配置,生成的代理对象就知道如何调用--aop:aspect refmyutil!--前置通知先输出通知在执行方法--aop:before methodprintLog pointcut-refsaveAdmin/aop:before/aop:aspect/aop:config
/beanspackage com.ffyc.ssm.util;/* 提取的非业务的功能称为通知通知又分为5种: 前置通知、后置通知、异常通知、最终通知、环绕通知*/
public class MyUtil {public void printLog(){System.out.println(打印日志);}public void commit(){System.out.println(提取事务);}public void exceptionAdvice(Throwable e){System.out.println(异常通知e.getMessage());}
}package com.ffyc.ssm.dao;Repository(value adminDao)
//目标类
public class AdminDao {AutowiredJdbcTemplate jdbcTemplate;/*连接点:类中可以被增强的方法,称为连接点切入点: 类中实际被增强的方法,横切面切入的方法*/public void saveAdmin(Admin admin){System.out.println(保存管理员);}public void updateAdmin(Admin admin){System.out.println(修改管理员);}
}public class Test3 {public static void main(String[] args) {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);AdminService adminServiceapp.getBean(adminService,AdminService.class);adminService.save(admin);}
}通知又分为5种: 前置通知业务方法执行前调用 后置通知(after-returning)业务方法执行后调用当方法出现异常不执行 异常通知 (after-throwing)业务方法出现异常时调用 最终通知(after)业务方法执行后调用当方法出现异常也会执行 环绕通知环绕通知包含前四种通知
package com.ffyc.ssm.util;public class MyUtil {/*ProceedingJoinPoint需要调用的方法*/public void aroundAdvice(ProceedingJoinPoint point){try {System.out.println(前置通知);point.proceed();//调用我们自己的业务方法System.out.println(后置通知);} catch (Throwable throwable) {throwable.printStackTrace();System.out.println(异常通知throwable.getMessage());}System.out.println(最终通知);}
}aop:config!--配置切入点--aop:pointcut idsaveAdmin expressionexecution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..))/!--将通知与切入点进行配置,生成的代理对象就知道如何调用--aop:aspect refmyutilaop:around methodaroundAdvice pointcut-refsaveAdmin/aop:around/aop:aspect
/aop:config2、注解方式的实现
1.开启自动代理
!--spring.xml中开启自动代理--
aop:aspectj-autoproxy /2.Component //让spring管理生成对象 Aspect //表明装有通知的类/切面
package com.ffyc.ssm.util;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;Component //让spring管理生成对象
Aspect //表明装有通知的类/切面
public class MyUtil {//Before(execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..)))//AfterReturning(execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..)))//After(execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..)))public void printLog(){System.out.println(打印日志);}public void commit(){System.out.println(提取事务);}//AfterThrowing(value execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..)),throwing e)public void exceptionAdvice(Throwable e){System.out.println(异常通知e.getMessage());}/*ProceedingJoinPoint需要调用的方法*/Around(execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..)))public void aroundAdvice(ProceedingJoinPoint point){try {System.out.println(前置通知);point.proceed();//调用我们自己的业务方法System.out.println(后置通知);} catch (Throwable throwable) {throwable.printStackTrace();System.out.println(异常通知throwable.getMessage());}System.out.println(最终通知);}
}spring事务管理
jdbc自动事务提交mybatis里面事务默认不自动提交需要我们在程序中手动提交 sqlsession.commit()spring框架把提交事务的功能帮助我们管理起来了封装好了。 事物可以看做是由对数据库若干操作组成的一个单元。案例转账 关系型数据库事务基本特征: 1.原子性保障一个事务中的多条sql要么都执行要么都不执行 2.隔离性 3.持久性 4.一致性 我们在开发企业应用时对于业务人员的一个操作实际是对数据读写的多步操作的结合。由于数据操作在顺序执行的过程中任何一步操作都有可能发生异常 异常会导致后续操作无法完成此时由于业务逻辑并未正确的完成之前成功操作数据的并不可靠需要在这种情况下进行回退。 事务的作用就是为了保证用户的每一个操作都是可靠的事务中的每一步操作都必须成功执行只要有发生异常就回退到事务开始未进行操作的状态这些操作要么都完成要么都取消从而保证数据满足一致性的要求 Spring 中的事务管理分两种 1.编程式事务管理在代码中写实际开发中使用的少。这种方式需要注入一个事务管理对象TransactionTemplate然后在我们代码中需要提交事务或回滚事务时自己写代码实现。
public class AdminDao {AutowiredJdbcTemplate jdbcTemplate;AutowiredTransactionTemplate transactionTemplate;public void saveAdmin(Admin admin){System.out.println(保存管理员);transactionTemplate.execute(new TransactionCallbackObject() {Overridepublic Object doInTransaction(TransactionStatus transactionStatus) {jdbcTemplate.update(insert into admin(account,password)value(?,?),aa,aa);int i10/0;jdbcTemplate.update(insert into admin(account,password)value(?,?),bb,bb);return null;}});}
}2.声明式事务管理使用注解标签标实现底层实现原理就是AOP的思想本质是对方法前后进行拦截是方法级别的在执行某个方法时为方法添加额外的事务管理功能 Spring 声明式事物管理方式有两种
基于 xml 配置基于注解实现 Spring 针对不同的 dao 框架提供了不同的实现类Jdbcmybatis事物管理实现类是 DataSourceTransactionManager. 1jar包
!-- spring-jdbc --
dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.2.2.RELEASE/version
/dependency2配置事物管理器、注解方式
!-- 配置spring事务管理类, 并注入数据源。db.xml --
bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property
/bean!--开启注解事务管理。db.xml--
tx:annotation-driven transaction-managertransactionManager/3Transactional 注解标签
public class AdminDao {
Autowired
JdbcTemplate jdbcTemplate;Transactional
public void saveAdmin(Admin admin){System.out.println(保存管理员);jdbcTemplate.update(insert into admin(account,password)value(?,?),aa,aa);int i10/0;jdbcTemplate.update(insert into admin(account,password)value(?,?),bb,bb);
}Transactional标签的用法
一般把事务管理的注解标签在service的方法中来进行控制。因为dao层是接口一个接口对应一个sql在一个业务逻辑中可能要执行多个dao层的sql需要把这多个sql放在同一个事务管理中进行Transactional可以添加在service层中类上类中所有的方法都会添加事务管理功能Transactional如果只添加在某个方法上那么表示此方法在事务管理中进行 案例转钱 这个案例中如果service层没有Transactional而dao有Transactional可能会出现问题。加减是独立的的事务不是同一个事务
package com.ffyc.ssm.service;Service(value adminService)
public class AdminService {
//对于service层来讲转账是一个操作
Transactionalpublic void zhuanzhang(){int id11;int id27;int money500;//调用不同的层的方法adminDao.jian(id1,money);System.out.println(10/0);adminDao.jia(id2,money);}
}package com.ffyc.ssm.dao;Repository(value adminDao)
//目标类
public class AdminDao {AutowiredJdbcTemplate jdbcTemplate;//减钱public void jian(int id1,int m){jdbcTemplate.update(update admin set moneymoney-m where id?,id1);}//加钱public void jia(int id2,int m){jdbcTemplate.update(update admin set moneymoneym where id?,id2);}
}package com.ffyc.ssm.test;public class Test3 {public static void main(String[] args) {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);AdminService adminServiceapp.getBean(adminService,AdminService.class);adminService.zhuanzhang();}
}Transactional 声明式注解事务管理在以下情况会失效:重点 1.修饰非public的方法底层权限只针对public修饰的方法 2.方法中的异常被catch捕获处理了
Transactional
public void zhuanzhang(){int id11;int id27;int money500;//调用不同的层的方法adminDao.jian(id1,money);try{System.out.println(10/0);}catch (Exception e){System.out.println(算术异常);}adminDao.jia(id2,money);
}
//方法中出现异常但是却正常转账了是不正常的3.出现编译期异常事务不生效 默认情况下事务只对运行期异常进行生效Transactional(rollbackFor RuntimeException.class) 我们可以把其修改为**Transactional(rollbackFor Exception.class)这样就可以处理任意的异常**
Transactional(rollbackFor Exception.class)//出现编译期异常事务也会生效
public void zhuanzhang() throws UnsupportedEncodingException {int id11;int id27;int money500;adminDao.jian(id1,money);abc.getBytes(utf--8);adminDao.jia(id2,money);
}4.Transactional事务传播行为设置错误 5.数据库引擎不支持事务。数据库引擎是mysql底层具体的一种数据处理实现的机制 常用的两个引擎innodb(支持事务功能)myisam(不支持事务) 6.同一个类中使用非代理对象调用一个有事务的方法 在一个非事务方法中使用this(原始的对象自己new出来的对象)
public class AdminService {//this表示自己没有被spring进行任何增强的 最原始的new出来的对象//如果是spring生成的对象spring会根据这个方法上所添加的注解标签来做一些额外的增强会返回一个代理对象Transactional(rollbackFor Exception.class)//加上这个就好了public void test() throws UnsupportedEncodingException {this.zhuanzhang();}Transactional(rollbackFor Exception.class)public void zhuanzhang() throws UnsupportedEncodingException {int id11;int id27;int money500;//调用不同的层的方法adminDao.jian(id1,money);abc.getBytes(utf--8);adminDao.jia(id2,money);}
}public class Test3 {public static void main(String[] args) throws UnsupportedEncodingException {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);AdminService adminServiceapp.getBean(adminService,AdminService.class);adminService.test();}
}事务传播行为
事务功能本质上属于mysql数据库 spring事务管理指的是spring框架可以帮助我们进行事务开启、提交、回滚 什么叫事务传播行为 即然是传播那么至少有两个方法才可以发生传播单体不存在传播这个行为。 事务传播行为propagation behavior指的就是当一个事务方法被另一个事务方法调用时这个事务方法应该如何进行。事务传播行为是 Spring 框架独有的事务增强特性不属于事务实际提供者mysql. 例如A事务方法调用B事务方法时B事务是一个独立的事务呢独立的表示B出现了问题不影响A?还是B事务合并到A事务中呢B影响AA影响B这就是由B的事务传播行为决定的 要么多个事务嵌套在一个中要么多个事务相互独立运行。 Spring 定义了七种传播行为
事务传播行为类型说明PROPAGATION_REQUIRED如果A有事务 B加入到A事务中如果A没有事务B就新建一个事务与A没有关系。常见PROPAGATION_REQUIRES_NEW无论A是否有事务B都会创建新的事务独立的PROPAGATION_SUPPORTS支持A事务如果A没有事务B就以非事务方式执行PROPAGATION_NEVERB以非事务方式执行如果A存在事务则抛出异常。PROPAGATION_MANDATORY使用A事务如果A没有事务就抛出异常。PROPAGATION_NOT_SUPPORTED以非事务方式执行操作如果当前存在事务就把当前事务挂起PROPAGATION_NESTED如果当前存在事务则在嵌套事务内执行。如果当前没有事务 则执行与 PROPAGATION_REQUIRED 类似的操作。
注意事务传播行为不能是同一个类中的方法相互调用必须是一个类中的方法调用另一个类中的方法
案例保存管理员时需要向日志表里插入一条记录
1、PROPAGATION_REQUIRED A事务方法调用B方法传播行为REQUIRED。如果A方法有事务B加入到A方法事务中任意一方出现异常都会回滚A方法没有事务B方法会自己创建一个事务与A没有关系。 AdminService中save的调用LogService中的saveLog方法两个方法都有事务调用saveLog时就加入到save中合二为一如果出现异常两者SQL都不会执行
Service(value adminService)
public class AdminService {AutowiredAdminDao adminDao;AutowiredLogService logService;//AdminService调用LogServiceTransactional(propagation Propagation.REQUIRED)public void save(Admin admin){adminDao.saveAdmin(admin);logService.saveLog();//save调用saveLog方法System.out.println(10/0);}
}Repository(value adminDao)
public class AdminDao {AutowiredJdbcTemplate jdbcTemplate;public void saveAdmin(Admin admin){System.out.println(保存管理员);jdbcTemplate.update(insert into admin(account,password)value(?,?),ff,ff);}
}Service(value logService)
public class LogService {AutowiredLogDao logDao;Transactional(propagation Propagation.REQUIRED)public void saveLog(){logDao.saveLog();}
}Repository(value logDao)
public class LogDao {AutowiredJdbcTemplate jdbcTemplate;public void saveLog(){jdbcTemplate.update(insert into log(oper_time)value(now()));}
}public class Test3 {public static void main(String[] args) throws UnsupportedEncodingException {ClassPathXmlApplicationContext appnew ClassPathXmlApplicationContext(spring.xml);Admin adminapp.getBean(admin,Admin.class);AdminService adminServiceapp.getBean(adminService,AdminService.class);adminService.save(admin);}
}save没有事务saveLog有事务此时saveLog会新建一个事务与save没有关系。保存管理员正常执行。结果保存管理员也可以打印日志
Service(value adminService)
public class AdminService {AutowiredAdminDao adminDao;AutowiredLogService logService;//AdminService调用LogServicepublic void save(Admin admin){adminDao.saveAdmin(admin);//正常执行logService.saveLog();//save调用saveLog方法新建一个事务System.out.println(10/0);}
}Service(value logService)
public class LogService {AutowiredLogDao logDao;Transactional(propagation Propagation.REQUIRED)public void saveLog(){logDao.saveLog();}
}save没有事务saveLog有事务此时saveLog会新建一个事务异常在saveLog中保存管理员正常执行而保存日志有异常而不会执行
Service(value adminService)
public class AdminService {AutowiredAdminDao adminDao;AutowiredLogService logService;//AdminService调用LogServicepublic void save(Admin admin){adminDao.saveAdmin(admin);logService.saveLog();//save调用saveLog方法}
}Service(value logService)
public class LogService {AutowiredLogDao logDao;Transactional(propagation Propagation.REQUIRED)public void saveLog(){logDao.saveLog();System.out.println(10/0);}
}2、PROPAGATION_REQUIRES_NEW 无论A是否有事务B都会创建新的事务独立的 两者是独立的事务异常在save中保存管理员不执行保存日志执行 AutowiredAdminDao adminDao;AutowiredLogService logService;//AdminService调用LogServicepublic void save(Admin admin){adminDao.saveAdmin(admin);logService.saveLog();System.out.println(10/0);}
}Service(value logService)
public class LogService {AutowiredLogDao logDao;Transactional(propagation Propagation.REQUIRES_NEW)public void saveLog(){logDao.saveLog();}
}3、PROPAGATION_NEVER B以非事务方式执行如果A存在事务则抛出异常。 saveLog在非事务的方法中执行如果save中有事务则会抛出异常
public class AdminService {AutowiredAdminDao adminDao;AutowiredLogService logService;//AdminService调用LogServiceTransactionalpublic void save(Admin admin){adminDao.saveAdmin(admin);logService.saveLog();}
}Service(value logService)
public class LogService {AutowiredLogDao logDao;Transactional(propagation Propagation.NEVER)public void saveLog(){logDao.saveLog();}
}