网贷网站建设,仁寿县建设局网站,网站建设与管理代码样式,房屋建模软件目录
一、Spring概述
#xff08;一#xff09;、Spring是什么#xff1f;
#xff08;二#xff09;、Spring框架发展历程
#xff08;三#xff09;、Spring框架的优势
#xff08;四#xff09;、Spring的体系结构
二、程序耦合与解耦合
#xff08;一一、Spring是什么
二、Spring框架发展历程
三、Spring框架的优势
四、Spring的体系结构
二、程序耦合与解耦合
一什么是程序的耦合
二解决程序耦合的思路
1、编译不依赖运行时才依赖
2、使用工厂模式解耦合
三、SpringIOC机制的详解
一、IOC概述及作用
1、IOC的简介设计思想
2、IOC作用
二SpringIOC入门案例前期准备
1、构建maven工程添加Spring框架的依赖
2、创建持久层接口和实现类
3、创建业务层接口和实现类
4、在resources文件夹中创建一个任意名称的xml文件
5、让Spring管理资源在配置文件中配置service和dao
6、测试IOC配置是否成功
三Spring基于XML的IOC细节
1、IOC配置文件详解配置标签书写规范配置标签的属性
2、SpringIOC机制源码解析 1 IOC容器解析 2IOC容器底层bean初始化过程
四手动实现自己的IOC容器
1、分析IOC实现思路
2、IOC原理实现—环境搭建构建maven工程引入依赖
3、设计接口和类以及编写配置文件
4、使用xml技术解析配置文件
5、编写测试文件展示测试结果
五Spring管理bean细节
1、bean实例化方式
1构造方法的方式
1创建User类
2配置Spring容器管理user类型对象
3测试容器实例化User对象是否成功
2静态工厂方式
1创建静态工厂ItemFactory
2配置Spring容器管理User类型对象
3测试容器实例化User对象是否成功
3实例工厂方式
1创建实例工厂NewItemFactory
2配置Spring容器管理NewItemFactory类型对象
3测试容器实例化User对象是否成功
2、bean作用域
1bean作用域介绍
2bean作用域的解析
1当scope的取值为singleton时
2当scope的取值为prototype时
3当Scope的取值为其他值
四、Spring依赖注入DI 一介绍
定义
二注入方式
1、构造函数注入
1构建Account类提供所有属性的构造方法
2配置Account类使用构造方法注入依赖数据
3构造函数注入测试方法
2、setter注入
1修改Account类添加属性的setter方法
2配置Account类利用setter方法注入依赖数据
3setter注入测试方法
3、注入集合数据
1修改Account类添加集合属性
2配置Account类利用setter注入依赖集合数据
3集合注入测试方法
五、Spring配置文件模块化
一Spring模块化的介绍
二Spring模块化的配置
1、Spring模块化配置方式一
2、Spring模块化配置方式二
六、模块设计模式解析
一模块化设计模式介绍
二模板设计模式的应用场景
三模板设计模式实现
1、需求用模块方法模式实现出国留学手续设计程序
2、代码实现
七、Spring整合JDBC实现用户的CRUD
一整合思路分析
二构建maven工程添加技术依赖
三构建数据库表并编写实体类Account
四编写持久层代码AccountDao以及实现类AccountDaoImpl
五编写业务层代码Accountservice以及实现类AccountServiceImpl
六创建并编写配置文件配置容器管理对象
七测试代码 八、常用注解
一创建对象的注解
二用于注入数据的注解
三用于改变作用范围的注解
九、基于注解的IOC案例
一构建工程添加依赖
二使用注解配置
三创建配置文件并开启对注解的支持
四编写测试代码
十、纯注解配置
一新注解说明
二通过注解获取容器
十一、Spring整合Junit
一IOC测试类中的问题和解决思路
二整合Junit配置步骤
1、添加技术依赖
2、使用RunWith注解替换原有运行器
3、使用ContextConfiguration 指定 Spring 配置文件的位置
4、使用Autowired 给测试类中的变量注入数据
十二、Spring整合DButils实现转账业务
一添加转账方法并演示事务问题
1、转账Account表以及对应的实体bean
2、引入DBUtils依赖坐标
3、创建Account接口和对应实现类
4、创建AccountService接口和实现类
5、测试转账业务
二编写ConnectionUtils工具类管理数据库连接
三编写事务管理工具类
四编写业务层和持久层控制代码并配置Spring的IOC
五测试转账
六转账业务案例中存在的问题
七使用动态代理实现事务控制
1、创建代理工具类
2、配置并测试动态代理转账业务
十三、SpringAOP机制详解 一AOP概述
1、什么是AOP
2、AOP编程思想
3、Spring中的常用术语
4、AOP编程底层的实现机制
1JDK动态代理
2CGLB动态代理
5、AOP的作用及优势
二Spring基于XML的AOP配置
1、环境搭建
1添加依赖
2添加代码
3创建配置文件并导入约束
4配置Spring的IOC
5抽取公共代码制作成通知
2、AOP配置步骤
1配置bean标签
2使用aopconfig 声明AOP配置
3使用aopaspect 配置切面
4使用aoppointcut配置切入点表达式
5使用aopxxx配置对应的通知类型
3、切入点表达式说明
4、环绕通知配置事务管理
三Spring基于注解的AOP配置
1、环境搭建
1构建maven工程添加AOP注解的相关依赖
2导入代码
3在配置文件中导入context的名称空间且配置
4资源使用注解配置
5在配置文件中指定spring要扫描的包
2、配置步骤
1通知类使用注解配置
2通知类使用Aspect注解声明为切面
3增强方法上使用注解配置通知
4开启Spring对注解AOP的支持
5环绕通知注解配置
6切入点表达式注解
十四、Spring事务详解
一Spring基于XML的事务配置
1、环境搭建
1构建工程添加依赖
2创建Spring的配置文件导入约束
3沿用转账业务
2、事务管理配置步骤
1配置事务管理器
2配置事务的通知引用事务管理器
3配置事务的属性
4配置AOP切入点表达式
5配置切入点表达式和事务通知的对应关系
二Spring基于注解的事务配置
1、环境搭建
1构建maven工程添加相关依赖
2创建Spring配置文件
3沿用转账业务的代码dao实现类和service实现类采用注解的形式添加到容器中管理
2、事务管理配置步骤
1配置事务管理器并注入数据源
2在业务层使用Transactional注解
3配置文件中开启Spring对注解事务的支持
十五、Spring整合Mybatis实现用户的CRUD
一整理思路分析
二构建maven工程添加依赖
三构建数据库表并创建实体类
四编写dao层的接口UserMapper
五构建mapper接口对应的sql配置文件
六构建服务层接口UserService
七构建服务层实现类UserServiceImpl
八构建配置文件
九测试代码 一、Spring概述
一、Spring是什么
Spring是一个分层的java SE/EE full-stack一站式轻量级开源框架以IOC控制反转和AOP面向切面编程为内核。
在java三层架构当中分别提供了相应的技术
表现层web层SpringMVC框架
业务层service层Bean管理IOC容器
持久层dao层jdbcTemplate模板对象以及提供了ORM模块整合其他优秀的持久层技术。
二、Spring框架发展历程
1997年IBM提出了EJB的思想。1998年SUN制定开发标准规范EJB1.0.。199年EJB1.1发布。2001年EJB2.0发布。2006年EJB3.0发布。 Rod Johnson Spring 之父 Expert One-to-One J2EE Design and Development(2002) 阐述了 J2EE 使用EJB 开发设计的优点及解决方案 Expert One-to-One J2EE Development without EJB(2004) 阐述了 J2EE 开发不使用 EJB的解决方式Spring 雏形 2017 年 9 月份发布了 Spring 的最新版本 Spring5.0 通用版GA 三、Spring框架的优势
方便解耦简化开发Spring就是一个工厂可以管理所有对象的创建和依赖关系维护交给Spring管理。
AOP编程的支持可以方便的实现对程序进行权限拦截日志记录运行的监控。
声明式事务的支持通过配置的方式完成对事务的管理无需手动编程。
方便程序的测试对Junit支持可以通过注解方式方便的对Spring程序进行测试。
整合外部优秀技术Spring内部提供了对各种优秀框架HibernateMybatis的直接支持。
javaEE技术的封装;Spring对javaEE开发当中复杂难用的API进行封装降低了这些API的使用难度。
四、Spring的体系结构 二、程序耦合与解耦合
一什么是程序的耦合
程序的耦合是程序之间的关联性也就是多个类的联系是否紧密多个对象之间的关系是否密切。 生活中的案例 你的房子里面有窗子那么房子和窗子就有了关联 耦合度是松还是紧就看你的关联是强还是弱也就是修改的代价比如你窗子是扣死在墙里的那么你修改窗子就必须修改墙 这就比较紧密了反应在程序上就是耦合度高不利于程序的扩展和维护。 但是如果你窗子是按照某种规格的 可以自由拆装的那么修改的代价就小耦合度也就低了反应在程 序上就是耦合度低利于程序的扩展和维护。 我们写程序的目标就是 高内聚 低耦合 二解决程序耦合的思路
1、编译不依赖运行时才依赖
当我们讲解jdbc时是通过反射来注册驱动的代码如下
Class.forName(com.mysql.jdbc.Driver);//使用的驱动类是指定了一个字符串
我们的类中在编译阶段不再需要具体的驱动类就算删除mysql的驱动jar包依然可以通过编译。在运行阶段才会依赖驱动包。实际开发当中我们应该做到编译不依赖运行时才依赖。
上述代码产生的新问题mysql驱动类的全限定类名作为一个字符串java类中是写死的一旦发生改变还需要修改源码。
使用配置文件结合反射就可以解决上述问题。
2、使用工厂模式解耦合
在实际开发中我们可以把三层的对象都使用配置文件配置起来当启动服务器应用加载的时候让一个类中的方法通过读取配置文件把这些对象创建出来并存起来。在接下来的使用的时候直接拿过来用就好了。
那么这个读取配置文件创建和获取三层对象的类就是工厂。 三、SpringIOC机制的详解
一、IOC概述及作用
1、IOC的简介设计思想
SpringIOCIOC是Inversion of Control的缩写多数书籍翻译成“控制反转”。
IOC这个概念简单来说就是把复杂系统分解成相互合作的对象这些对象类通过封装以后内部实现对外部透明的从而降低了解决问题的复杂度而且可以灵活的被重用和扩展。
IOC理论提出的观点大体是这样的借助于第三方实现具有依赖关系的对象之间的解耦。 由于引进了中间位置“第三方”也就是IOC容器使得A、B、C、D这四个对象没有了耦合关系齿轮之间的传动全部依靠IOC容器全部对象的控制权上交给IOC容器所以IOC容器成了整个系统的关键核心它起到一个“粘合剂”的作用把系统中所有对象粘合在一起发挥作用。 当把图中的IOC容器拿掉可以发现A、B、C、D这四个 对象之间没有耦合关系。这样的话当我们去实现A的时候根本无需去考虑其他几个对象对象之间的依赖关系已经讲到了最低程度。
2、IOC作用
IOc本质上就是一个大工程大容器。主要作用就是创建和管理对象的依赖关系削减计算机程序的耦合解除我们代码间的依赖关系提高程序的可扩展性和可维护性。 二SpringIOC入门案例前期准备
1、构建maven工程添加Spring框架的依赖
propertiesspring.version5.2.5.RELEASE/spring.version
/properties
!--导入spring的context坐标context依赖core、beans、expression aop--
dependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependency
/dependencies
2、创建持久层接口和实现类
public interface UserDao {public void save();
}public class UserDaoImpl implements UserDao {Overridepublic void save() {System.out.println(userDao save method running...... );}
}
3、创建业务层接口和实现类
public interface UserService {public void saveService();
}public class UserServiceImpl implements UserService {Overridepublic void saveService() {System.out.println(userSerivce save method running......);}
}
4、在resources文件夹中创建一个任意名称的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/springbeans.xsd
/beans
5、让Spring管理资源在配置文件中配置service和dao
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd!--配置userDaoImpl--bean iduserDao classcom.ujiuye.dao.impl.UserDaoImpl/bean!--配置userServiceImpl--bean iduserService classcom.ujiuye.service.UserServiceImpl/bean
/beans
6、测试IOC配置是否成功
Test
public void test1(){//1获得spring IOC容器对象ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);//2:从容器当中根据id获得UserDaoImpl 对象,执行userDao对象的save方法UserDao userDao (UserDao) applicationContext.getBean(userDao);userDao.save();//3:从容器当中根据id获得UserServiceImpl 对象,执行userService对象的saveService
方法UserService userService (UserService)applicationContext.getBean(userService);userService.saveService();
}
运行结果 三Spring基于XML的IOC细节
1、IOC配置文件详解配置标签书写规范配置标签的属性
bean标签用于配置对象交给Spring来创建 默认情况下他会调用类中无参数的构造器如果没有无参数构造器则不能创建成功。
基本属性 idBean实例对象在Spring容器中的唯一标识 classBean的全限定类名
2、SpringIOC机制源码解析 1 IOC容器解析 IOC思想基于IOC容器完成IOC容器底层就是对象工厂Spring中工厂的类结构图如下; 1BeanFactoryIOC容器的基本实现是Spring内部使用的接口不提供开发人员使用加载配置文件时不会创建对象在获得使用对象时才采取创建对象。 2HierarchicalBeanFactory这个工厂接口非常简单实现了Bean工厂的分层。工厂接口也是继承自BeanFactory也是一个二级接口相对于父接口他只是扩展了一个重要的功能———工厂分层 3AutowireCapableBeanFactory该接口有自动配置能力需要注意的是ApplicationContext接口并实现此接口因为应用代码很少用到此功能如果确实需要的话可以调用ApplicationContext的getAutowireCapableBeanFactory方法来获取此接口的实例 4ListableBeanFactory获取bean时Spring鼓励使用这个接口定义的api如查看bean
的个数、获取某一类型Bean的配置名、查看容器中是否包括某一Bean等方法。 5ApplicationContextBeanFactory接口的子接口提供更多强大的功能一般由开发人员使用。接口提供了bean基础性操作同时扩展了国际化等功能。ApplicationContext接口在加载配置文件时候就会配置文件当中的对象进行创建存放IOC容器当中 6AnnotationConfigApplicationContext当使用注解配置容器对象时需要使用此类来创建spring容器。他用来读取注解。 7ClassPathXmlApplicationContext它是从类的根路径下加载配置文件 8FileSystemXmlApplicationContext它是从磁盘路径上加载配置文件配置文件可以在磁盘的任意位置。 2IOC容器底层bean初始化过程 1BeanFactionPostProcessor 作用定义了在bean工厂对象创建后bean对象创建前执行的动作用于对工厂进行创建后业务处理 运行时机操作用于对工厂进行处理仅运行一次 2) BeanPostProcessor 作用定义了所有bean初始化前后进行的统一动作用于对bean进行创建前业务处理与创建后业务处理 运行时机当前操作伴随着每个bean的创建过程每次创建bean均运行该操作。 3InitializingBean 作用定义了每个bean的初始化前进行的动作属于非统一性动作用于对bean进行创建前业务处理。 运行时机当前操作伴随着任意一个bean的创建过程保障其个性化业务处理
四手动实现自己的IOC容器
1、分析IOC实现思路 2、IOC原理实现—环境搭建构建maven工程引入依赖
propertiesspring.version5.2.5.RELEASE/spring.version/propertiesdependencies!--导入spring的context坐标--dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependency!--导入junit单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency/dependencies
3、设计接口和类以及编写配置文件
//设定UserDao接口
public interface UserDao {public void save();
}
//设定UserDao接口实现类
public class UserDaoImpl implements UserDao {Overridepublic void save() {System.out.println(userDao save method running...... );}
}
配置文件
!--配置userDaoImpl--
bean iduserDao classcom.ujiuye.dao.impl.UserDaoImpl/bean
4、使用xml技术解析配置文件
!--引入dom4J--
dependencygroupIddom4j/groupIdartifactIddom4j/artifactIdversion1.6.1/version
/dependency
/**
* 创建自己的工厂类
*/
public class MyBeanFactory {//创建一个map集合模拟IOC容器private static MapString,Object map new HashMap();static{try {//使用dom4J 解析xml文件//第一步获得一个解析器SAXReader reader new SAXReader();//第二 读取外部的配置文件String path src/main/resources/applicationContext.xml;//第三: 读取了整个文档对象Document document reader.read(path);//第四 获得根节点Element rootElement document.getRootElement();//beans//第五 获得根节点下的所有的bean 标签对应的节点ListElement bean rootElement.elements(bean);// beanfor (Element element : bean) {//获得id属性对应的值String id1 element.attributeValue(id);//获得class属性对应的值【全限定类名】String aClass element.attributeValue(class);//获得class对应的值 全限定类名。//通过反射创建对象Class clz Class.forName(aClass);Object object clz.newInstance();//存容器 id做key创建出来的对象valuemap.put(id1,object);}} catch (Exception e) {e.printStackTrace();}
}
/**
* 根据id从容器当中获得对象
* param id id的名称
* return 返回Object类型对象
*/
public static Object getBean(String id){Object o map.get(id);return o;}
}
5、编写测试文件展示测试结果
Test
public void testMyFactory(){//1创建工厂对象MyBeanFactory factory new MyBeanFactory();//2从容器当中根据id获得对象UserDao userDao (UserDao) factory.getBean(userDao);System.out.println(userDao);userDao.save();
} 五Spring管理bean细节
1、bean实例化方式
1构造方法的方式
1创建User类
public class User implements Serializable {public User(){System.out.println(user created...);}
} 2配置Spring容器管理user类型对象
!--配置user对象--
bean iduser classcom.ujiuye.pojo.User/bean 3测试容器实例化User对象是否成功
Test
public void testUser(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);User user (User) context.getBean(user);System.out.println(user);
} 2静态工厂方式
1创建静态工厂ItemFactory
public class ItemFactory {//静态方法返回实例beanpublic static User createUser(){System.out.println(static method running create bean ......);return new User();}
} 2配置Spring容器管理User类型对象
!--静态工厂实例化对象--
bean iduser classcom.ujiuye.factory.ItemFactory/bean 3测试容器实例化User对象是否成功
Test
public void testItemFactory(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);User user (User) context.getBean(user);System.out.println(user);
} 3实例工厂方式
1创建实例工厂NewItemFactory
public class NewItemFactory {//工厂的非静态方法返回bean实例public User createUser(){System.out.println(Dynamic method running create bean ......);return new User();}
} 2配置Spring容器管理NewItemFactory类型对象
!--实例工厂--
bean iditemFactory classcom.ujiuye.factory.NewItemFactory/bean
bean iduser factory-beanitemFactory factory-methodcreateUser/bean
3测试容器实例化User对象是否成功
Test
public void testNewItemFactory(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);User user (User) context.getBean(user);System.out.println(user);
} 2、bean作用域
1bean作用域介绍
所谓Bean的作用域其实就是指Spring给我们创建出的对象的存活范围在配置文件中通过bean的scope属性指定
scope指对象的作用范围取值如下
取值范围说明singleton默认值单例的prototype多例的requestWEB 项目中Spring 创建一个 Bean 的对象将对象存入到 request 域中sessionWEB 项目中Spring 创建一个 Bean 的对象将对象存入到 session 域中global sessionWEB 项目中应用在 Portlet 环境如果没有 Portlet 环境那么globalSession 相当于 session 2bean作用域的解析
1当scope的取值为singleton时
Bean的实例化个数1个
Bean的实例化时机当Spring核心文件被加载时实例化配置的Bean实例
2当scope的取值为prototype时
Bean的实例化个数多个
Bean的实例化时机当调用getBean()方法时实例化Bean
3当Scope的取值为其他值
scope指定为其他值需要在特定的环境下使用。 四、Spring依赖注入DI 一介绍
定义
它是SpringBoot框架核心IOC的具体实现。组件之间的依赖关系由容器在应用系统运行期来决定也就是由动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。 二注入方式
1、构造函数注入
1构建Account类提供所有属性的构造方法 顾名思义就是使用类中的构造函数给成员变量赋值。注意赋值的操作不是我们自己做的而是通过配置的方式让 Spring 框架来为我们注入。具体代码如下 public class Account {
private String name;
private Integer age;
private Date birthday;public Account(String name, Integer age, Date birthday) {this.name name;this.age age;this.birthday birthday;}
}
2配置Account类使用构造方法注入依赖数据
!--使用构造函数的方式给account中的属性赋值
要求
类中需要提供一个对应参数列表的构造器函数涉及的标签
constructor-arg:属性
name 执行参数在构造器中的名称
value它能赋的值是基本数据类型和 String 类型
ref它能赋的值是其他 bean 类型也就是说必须得是在配置文件中配置过的 bean
--
bean idnow classjava.util.Date/bean
bean idaccount classcom.ujiuye.pojo.Accountconstructor-arg namename value王达/constructor-argconstructor-arg nameage value20/constructor-argconstructor-arg namebirthday refnow/constructor-arg
/bean
3构造函数注入测试方法
Test
public void testDI(){ClassPathXmlApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);Account account (Account) applicationContext.getBean(account);System.out.println(name:account.getName() age:account.getAge()birthday:account.getBirthday());//打印结果 name:王达 age:20 birthday:Thu Feb 04 13:53:45 CST 2021
} 2、setter注入
1修改Account类添加属性的setter方法
public class Account {private String name;private Integer age;private Date birthday;public Account() {}public Account(String name, Integer age, Date birthday) {this.name name;this.age age;this.birthday birthday;}public String getName() {return name;}public void setName(String name) {this.name name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday birthday;}}
2配置Account类利用setter方法注入依赖数据
!--使用set方法的方式给属性赋值
涉及的标签 property属性
name找的是类中set方法后面的部分
ref 给属性赋值是其他bean类型的
value给属性赋值是基本数据类型和 string 类型的
实际开发当中 此种方式用的比较多推荐使用
--bean idnow classjava.util.Date/bean
bean idaccount classcom.ujiuye.pojo.Accountproperty namename value张三丰/propertyproperty nameage value31/propertyproperty namebirthday refnow/property
/bean
3setter注入测试方法
Test
public void testDI(){ClassPathXmlApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);Account account (Account) applicationContext.getBean(account);System.out.println(name:account.getName() age:account.getAge()birthday:account.getBirthday());//测试结果 name:张三丰 age:31 birthday:Thu Feb 04 14:05:19 CST 2021
} 3、注入集合数据
1修改Account类添加集合属性 给类中的集合成员传值它用的也是set方法注入的方式只不过变量的数据类型都是集合。 我们这里介绍注入数组List,Set,Map,Properties。具体代码如下 public class Account {//注入数组List集合Set集合Map集合Properties集合属性private String[] myStrs;private ListString myList;private SetString mySet;private MapString,String myMap;private Properties myProps;public Account() {}public String[] getMyStrs() {return myStrs;}public void setMyStrs(String[] myStrs) {this.myStrs myStrs;}public ListString getMyList() {return myList;}public void setMyList(ListString myList) {this.myList myList;}public SetString getMySet() {return mySet;}public void setMySet(SetString mySet) {this.mySet mySet;}public MapString, String getMyMap() {return myMap;}public void setMyMap(MapString, String myMap) {this.myMap myMap;}public Properties getMyProps() {return myProps;}public void setMyProps(Properties myProps) {this.myProps myProps;}} 2配置Account类利用setter注入依赖集合数据 !--注入集合类型数据涉及到标签List结构 array list setMap结构 map entry props prop
--bean idaccount classcom.ujiuye.pojo.Account
!--注意在注入集合数据时只要是结构相同标签可以互换--!--注入数组数据--property namemyStrsarrayvaluearray-AAA/valuevaluearray-BBB/valuevaluearray-CCC/value/array/property!--注入List集合数据--property namemyListlistvaluelist-AAA/valuevaluelist-BBB/valuevaluelist-CCC/value/list/property!--注入Set集合数据--property namemySetlistvalueset-AAA/valuevalueset-BBB/valuevalueset-CCC/value/list/property!--注入Map集合--property namemyMapmapentry keymap-a valueAAA/entryentry keymap-bvalueBBB/value/entry/map/property!--注入Properties集合--property namemyPropspropsprop keypro-aAAA/propprop keypro-bBBB/prop/props/property
/bean 3集合注入测试方法
Test
public void testDI(){ClassPathXmlApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);Account account (Account) applicationContext.getBean(account);System.out.println(array: Arrays.toString(account.getMyStrs()));System.out.println(list:account.getMyList());System.out.println(set:account.getMySet());System.out.println(map:account.getMyMap());System.out.println(props:account.getMyProps());
/*
测试结果
array:[array-AAA, array-BBB, array-CCC]
list:[list-AAA, list-BBB, list-CCC]
set:[set-AAA, set-BBB, set-CCC]
map:{map-aAAA, map-bBBB}
props:{pro-bBBB, pro-aAAA}
*/
} 五、Spring配置文件模块化
一Spring模块化的介绍 我们现在的配置都集中配在了一个applicationContext.xml文件中当开发人员过多时 如果所有bean 都配置到同一个配置文件中会使这个文件巨大而且也不方便维护。 针对这个问题Spring提供了多配置文件的方式也就是所谓的配置文件模块化。 二Spring模块化的配置
1、Spring模块化配置方式一
并列的多个配置文件直接编写多个配置文件比如beans1.xmlbeans2.xml...然后在创建ApplicationContext的时候直接传入多个配置文件。
ApplicationContext act new ClassPathXmlApplicationContext(beans1.xml,beans2.xml,...); 2、Spring模块化配置方式二
主从配置文件先配置一个主配置文件然后在里面导入其他的配置文件。
import resourcebeans1.xml /
import resourcebeans2.xml /
注意 同一个xml文件中不能出现相同名称的bean如果出现会报错。‘’ 多个xml文件如果出现相同的名称的bean不会报错但是后加载的会覆盖前加载的bean所以企业开发中尽量保证bean的名称是唯一的。 六、模块设计模式解析
一模块化设计模式介绍
模块方法Template Method模式的定义定义一个操作中的算法骨架而将算法的一些步骤延迟到子类中使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
模块方法模式的静态结构图 二模板设计模式的应用场景
在多个子类中拥有相同的方法而且逻辑相同时可以将这些方法抽出来发到一个模块抽象类中程序主框架相同细节不同的情况下也可以使用模块方法。
举例说明 使用过Servlet的人都清楚除了要在web.xml做相应的配置外还需继承一个叫HttpServlet的抽象类。HttpService类提供了一个service()方法这个方法调用七个do方法中的一个或几个完成对客户端调用的响应。这些do方法需要由HttpServlet的具体子类提供因此这是典型的模板方法模式。 持久层对数据库的操作Spring提供了JdbcTemplate模板对象 完成CRUD操作。 三模板设计模式实现
1、需求用模块方法模式实现出国留学手续设计程序
分析出国留学手续一般经过以下流程索取学校资料提出入学申请办理因私出国护照、出境卡和公证申请签证体检、订机票、准备行装抵达目标学校等其中有些业务对各个学校是一样的但有些业务因学校不同而不同所以比较适合用模板方法模式来实现。 在本实例中我们先定义一个出国留学的抽象类 StudyAbroad里面包含了一个模板方法 TemplateMethod()该方法中包含了办理出国留学手续流程中的各个基本方法其中有些方法的处理由于各国都一样所以在抽象类中就可以实现但有些方法的处理各国是不同的必须在其具体子类如美国留学类 StudyInAmerica中实现。如果再增加一个国家只要增加一个子类就可以了。 2、代码实现
抽象类
//抽象类: 出国留学
public abstract class StudyAbroad {//定义抽象方法索取学校资料public abstract void LookingForSchool();//定义抽象方法定义入学申请public abstract void ApplyForEnrol();//定义入学申请方法public void ApplyForPassport() {System.out.println(三.办理因私出国护照、出境卡和公证);System.out.println( 1持录取通知书、本人户口簿或身份证向户口所在地公安机关申请办理因私出国护照和出境卡。);System.out.println( 2办理出生公证书学历、学位和成绩公证经历证书亲属关系公证经济担保公证。);}//定义申请签证方法public void ApplyForVisa() {System.out.println(四.申请签证);System.out.println( 1准备申请国外境签证所需的各种资料包括个人学历、成绩单、工作经历的证明个人及家庭收入、资金和财产证明家庭成员的关系证明等);System.out.println( 2向拟留学国家驻华使(领)馆申请入境签证。申请时需按要求填写有关表格递交必需的证明材料缴纳签证。有的国家(比如美国、英国、加拿大等)在申请签证时会要求申请人前往使(领)馆进行面试。);}//体检、订机票、准备行装 方法public void ReadyGoAbroad() {System.out.println(五.体检、订机票、准备行装);System.out.println( 1进行身体检查、免疫检查和接种传染病疫苗);System.out.println( 2确定机票时间、航班和转机地点。);}//定义抵达抽象方法public abstract void Arriving();}
子类
//定义具体的子类美国留学
public class StudyInAmerica extends StudyAbroad {//索取资料的具体实现Overridepublic void LookingForSchool() {System.out.println(一.索取学校以下资料);System.out.println( 1对留学意向国家的政治、经济、文化背景和教育体制、学术水平进行较为全面的了解);System.out.println( 2全面了解和掌握国外学校的情况包括历史、学费、学制、专业、师资配备、教学设施、学术地位、学生人数等);System.out.println( 3了解该学校的住宿、交通、医疗保险情况如何);System.out.println( 4该学校在中国是否有授权代理招生的留学中介公司);System.out.println( 5掌握留学签证情况);System.out.println( 6该国政府是否允许留学生合法打工);System.out.println( 8毕业之后可否移民);System.out.println( 9文凭是否受到我国认可);}//入学申请的具体实现Overridepublic void ApplyForEnrol() {System.out.println(二.入学申请);System.out.println( 1填写报名表);System.out.println( 2将报名表、个人学历证明、最近的学习成绩单、推荐信、个人简历、托福或雅思语言考试成绩单等资料寄往所申请的学校);System.out.println( 3为了给签证办理留有充裕的时间建议越早申请越好一般提前1年就比较从容。);}//抵达的具体实现Overridepublic void Arriving() {System.out.println(六.抵达目标学校);System.out.println( 1安排住宿);System.out.println( 2了解校园及周边环境。);}
}
public class StudyAbroadProcess {public static void main(String[] args) {StudyAbroad tm new StudyInAmerica();tm.TemplateMethod();}
} 七、Spring整合JDBC实现用户的CRUD
一整合思路分析
Spring提供了ioc容器管理jdbc操作数据库的过程中需要的数据库连接对象同时Spring提供了整合jdbc操作数据库的工具类JdbcDaoSupport 和模板工具 JdbcTemplate在JdbcTemplate中提供了大量的操作数据库的方式供用户使用。所以我们只需要获取模板工具类然后调用方法就可以完成Jdbc的操作了。 二构建maven工程添加技术依赖
dependencies!--导入spring的context坐标--dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependency!--导入Jdbc模块依赖--dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion${spring.version}/version/dependency!--导入Mysql 驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency!--导入C3P0连接池--dependencygroupIdcom.mchange/groupIdartifactIdc3p0/artifactIdversion0.9.5.2/version/dependency!--导入junit单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency
/dependencies 三构建数据库表并编写实体类Account
public class Account implements Serializable {private Integer id;private String name;private double money;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public double getMoney() {return money;}public void setMoney(double money) {this.money money;}Overridepublic String toString() {return Account{ id id , name name \ , money money };}
} 四编写持久层代码AccountDao以及实现类AccountDaoImpl
public interface AccountDao {public void save(Account account);public void delete(Integer id);public void update(Account account);public Account findById(Integer id);public Integer getTotalRecords();public ListAccount findAll();
}
public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate jdbcTemplate;}Overridepublic void save(Account account) {String sql insert into account(name,money) values(?,?);jdbcTemplate.update(sql,account.getName(),account.getMoney());}Overridepublic void delete(Integer id) {String sql delete from account where id ? ;jdbcTemplate.update(sql,id);}Overridepublic void update(Account account) {String sql update account set money ? , name? where id ?;jdbcTemplate.update(sql,account.getMoney(),account.getName(),account.getId());}Overridepublic Account findById(Integer id) {String sql select * from account where id ? ;Account account jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapperAccount(Account.class),id);return account;}Overridepublic Long getTotalRecords() {Long count jdbcTemplate.queryForObject(select count(*) from account,Long.class);System.out.println(count);return count;}Overridepublic ListAccount findAll() {String sql select * from account;ListAccount accountList jdbcTemplate.query(sql, new BeanPropertyRowMapperAccount(Account.class));return accountList;}
} 五编写业务层代码Accountservice以及实现类AccountServiceImpl
public interface AccountService {public void save(Account account);public void delete(Integer id);public void update(Account account);public Account findById(Integer id);public Long getTotalRecords();public ListAccount findAll();
}
public class AccountServiceImpl implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao accountDao;}Overridepublic void save(Account account) {accountDao.save(account);}Overridepublic void delete(Integer id) {accountDao.delete(id);}Overridepublic void update(Account account) {accountDao.update(account);}Overridepublic Account findById(Integer id) {return accountDao.findById(id);}Overridepublic Long getTotalRecords() {return accountDao.getTotalRecords();}Overridepublic ListAccount findAll() {return accountDao.findAll();}
} 六创建并编写配置文件配置容器管理对象
将数据库的连接信息抽取到外部配置文件中和spring的配置文件分离开有利于后期维护
jdbc.drivercom.mysql.jdbc.Driver
jdbc.urljdbc:mysql://localhost:3306/test
jdbc.usernameroot
jdbc.passwordroot
!--数据源对象--
bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSourceproperty namedriverClass value${jdbc.driver}/property namejdbcUrl value${jdbc.url}/property nameuser value${jdbc.username}/property namepassword value${jdbc.password}/
/bean!--配置JdbcTemplate模板对象--
bean idjdbcTemplate classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/
/bean!--配置AccountDaoImpl对象--
bean idaccountDao classcom.ujiuye.dao.impl.AccountDaoImplproperty namejdbcTemplate refjdbcTemplate/property
/bean!--配置AccountServiceImpl对象--
bean idaccountService classcom.ujiuye.service.AccountServiceImplproperty nameaccountDao refaccountDao/property
/bean 七测试代码
//测试save方法
Test
public void testJdbcTemplateSave(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);AccountService service (AccountService) context.getBean(accountService);Account account new Account();account.setName(jack);account.setMoney(1001D);service.save(account);
}//测试update方法
Test
public void testJdbcTemplateUpdate(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);AccountService service (AccountService) context.getBean(accountService);Account account new Account();account.setName(jack2);account.setMoney(999D);account.setId(1008);service.update(account);
}//测试delete方法
Test
public void testJdbcTemplateDelete(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);AccountService service (AccountService) context.getBean(accountService);service.delete(1001);
}//测试唯一性查询findById
Test
public void testJdbcTemplateFindById(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);AccountService service (AccountService) context.getBean(accountService);Account account service.findById(1001);System.out.println(account);
}//测试总记录数
Test
public void testJdbcTemplateGetTotalRecords(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);AccountService service (AccountService) context.getBean(accountService);Long totalRecords service.getTotalRecords();System.out.println(表当中的总记录数为totalRecords);
}//测试账户列表
Test
public void testJdbcTemplateGetAll(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);AccountService service (AccountService) context.getBean(accountService);ListAccount accountList service.findAll();accountList.forEach((account - {System.out.println(account);}));
} 八、常用注解
一创建对象的注解
注解说明Component使用在类上用于实例化BeanController使用在web层类上用于实例化BeanService使用在service层类上用于实例化BeanRepository使用在dao层类上用于实例化Bean
注意
使用注解进行开发时需要在applicationContext.xml中配置组件扫描作用是指定哪个包及其子包下的Bean需要进行扫描一便识别使用注解配置的类、字段和方法。
!--注解的组件扫描--
context:component-scan base-packagecom.ujiuye/context:component-scan 使用Component或Repository标识UserDaoImpl需要Spring进行实例化。
//Component(userDao)
Repository(userDao)
public class UserDaoImpl implements UserDao {Overridepublic void save() {System.out.println(save running... ...);}
} 使用Component或Service标识UserServiceImpl需要Spring进行实例化
//Component(userService)
Service(userService)
public class UserServiceImpl implements UserService {Overridepublic void save() {System.out.println(save running... ...);}
} 二用于注入数据的注解
注解说明Value注入普通属性Autowired 自动按照类型注入。当使用注解注入属性时set 方法可以省略。它只能注入其他 bean 类型。当有多个类型匹配时使用要注入的对象变量名称作为 bean 的id在 spring 容器查找找到了也可以注入成功。找不到就报错。 Qualifier 结合Autowired一起使用用于根据名称进行依赖注入 Resource 相当于AutowiredQualifier按照名称进行注入
使用Value进行字符串的注入
Repository(userDao)
public class UserDaoImpl implements UserDao {Value(注入普通数据)private String str;Value(${jdbc.driver})private String driver;Overridepublic void save() {System.out.println(str);System.out.println(driver);System.out.println(save running... ...);}
} 使用Autowired或者AutowiredQulifier或者Resource进行userDao的注入
//Component(userService)
Service(userService)
public class UserServiceImpl implements UserService {/*AutowiredQualifier(userDao)*/Resource(nameuserDao)private UserDao userDao;Overridepublic void save() {userDao.save();}
} 三用于改变作用范围的注解
注解说明Scope标注Bean的作用范围scope取值singleton prototype request session globalsession
使用Scope标注Bean的范围
//Scope(prototype)
Scope(singleton)
public class UserDaoImpl implements UserDao {//此处省略代码
} 九、基于注解的IOC案例
一构建工程添加依赖
dependencies!--导入spring的context坐标--dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependency!--导入Jdbc模块依赖--dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion${spring.version}/version/dependency!--导入Mysql 驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency!--导入C3P0连接池--dependencygroupIdcom.mchange/groupIdartifactIdc3p0/artifactIdversion0.9.5.2/version/dependency!--导入junit单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency
/dependencies 二使用注解配置
Repository(value userDao)
public class UserDaoImpl implements UserDao {Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic void save(User user) {String sql insert into user (name,birthday) values(?,?);jdbcTemplate.update(sql,user.getName(),user.getBirthday());}
}
Service(userService)
public class UserServiceImpl implements UserService {Autowiredprivate UserDao userDao ;Overridepublic void saveService(User user) {userDao.save(user);}
} 三创建配置文件并开启对注解的支持
context:component-scan base-packagecom.offcn/context:component-scan!--配置数据源--
bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSourceproperty namedriverClass valuecom.mysql.jdbc.Driver/propertyproperty namejdbcUrl valuejdbc:mysql://localhost:3306/test
/propertyproperty nameuser valueroot/propertyproperty namepassword valueroot/property
/bean
bean idjdbcTemplate classorg.springframework.jdbc.core.JdbcTemplateconstructor-arg namedataSource refdataSource/constructor-arg
/bean 四编写测试代码
//IOC 注解版本的案例
Test
public void test1(){ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);UserService userService (UserService) context.getBean(userService);User user new User();user.setName(admin);user.setBirthday(new Date());userService.saveService(user);
} 十、纯注解配置
一新注解说明
注解说明Configuration用于指定当前类是一个Spring配置类当创建容器时会从该类上加载注解ComponentScan用于指定Spring在初始化容器时要扫描的包。作用和在Springdexml配置文件中的contextcomponent-scan base-packagecom.offcn/一样Bean使用在方法上标注将该方法的返回值存储到Spring容器中PropertySource用于加载xxx.properties文件中的配置Import用于导入其他配置类
ConfigurationComponentScanImport
Configuration //指定当前类是一个配置类取代applicationContext.xml配置文件
ComponentScan(com.offcn) //指定Spring在初始化容器时要扫描的包
Import({xxx.class}) //导入其他的配置类
public class SpringConfiguration {...
}
PropertySourceValue
PropertySource(classpath:dbConfig.properties) //当前类中引入dbConfig.properties文件
public class DataSourceConfiguration {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
Bean(namedataSource) //将方法的返回值存入到IOC容器当中
public DataSource getDataSource() throws Exception {ComboPooledDataSource dataSource new ComboPooledDataSource();dataSource.setDriverClass(driver);dataSource.setJdbcUrl(url);dataSource.setUser(username);dataSource.setPassword(password);return dataSource;
} 二通过注解获取容器
public void AnnotationTest (){//使用AnnotationConfigApplicationContext获得ioc容器对象ApplicationContext context new AnnotationConfigApplicationContext(SpringConfig.class);Object obj context.getBean(...);
} 十一、Spring整合Junit
一IOC测试类中的问题和解决思路
在测试类中每个测试方法都有一下两行代码
ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);
UserService userService (UserService) context.getBean(userService);
这两行代码的作用是获取容器如果不写的话直接会提示空指针异常。所以又不能轻易删掉。 二整合Junit配置步骤
1、添加技术依赖
properties
spring.version5.2.5.RELEASE/spring.version
/properties!--此处需要注意的是spring5 及以上版本要求 junit 的版本必须是 4.12 及以上--
dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope
/dependency!--导入Spring整合Junit的依赖--
dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion${spring.version}/version
/dependency!--导入spring的context依赖--
dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version
/dependency 2、使用RunWith注解替换原有运行器
RunWith(SpringJUnit4ClassRunner.class)public class SpringJunitTest {
} 3、使用ContextConfiguration 指定 Spring 配置文件的位置
RunWith(SpringJUnit4ClassRunner.class)
//加载spring核心配置文件
//ContextConfiguration(value {classpath:applicationContext.xml})
//加载spring核心配置类
ContextConfiguration(classes {SpringConfiguration.class})
public class SpringJunitTest {
} 4、使用Autowired 给测试类中的变量注入数据
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(classes {SpringConfiguration.class})
public class SpringJunitTest {Autowiredprivate ApplicationContext context;Testpublic void test(){...}
} 十二、Spring整合DButils实现转账业务
一添加转账方法并演示事务问题
1、转账Account表以及对应的实体bean
public class Account implements Serializable {private Integer id;private String name;private double money;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public double getMoney() {return money;}public void setMoney(double money) {this.money money;}Overridepublic String toString() {return Account{ id id , name name \ , money money };}
} 2、引入DBUtils依赖坐标
!--引入QueryRunner--
dependencygroupIdcommons-dbutils/groupIdartifactIdcommons-dbutils/artifactIdversion1.7/version
/dependency 3、创建Account接口和对应实现类
public interface AccountDao {public Account findByName(String name);public void update(Account account);
}
public class AccountDaoImpl implements AccountDao {private QueryRunner queryRunner new QueryRunner(new ComboPooledDataSource());Overridepublic Account findByName(String name) {try {String sql select *from account where name ? ;Account account queryRunner.query(sql, new BeanHandler (Account.class), name);return account;} catch (SQLException throwables) {throwables.printStackTrace();}return null;}Overridepublic void update(Account account) {try {String sql update account set money ? where name ? ;queryRunner.update(sql, account.getMoney(), account.getName());} catch (SQLException throwables) {throwables.printStackTrace();}}
} 4、创建AccountService接口和实现类
public interface AccountService {
/**
* 定义业务方法 实现转账
* param sourceAccountName 来源账户
* param targetAccountName 目标账户
* param money 转账金额
*/public void transfer(String sourceAccountName,String targetAccountName,double money);
}
public class AccountServiceImpl implements AccountService {//依赖dao层private AccountDao accountDao new AccountDaoImpl();Overridepublic void transfer(String sourceAccountName, String targetAccountName, double money) {//查询来源账户和目标账户Account sAccount accountDao.findByName(sourceAccountName);Account tAccount accountDao.findByName(targetAccountName);//来源账户减钱目标账户加钱sAccount.setMoney(sAccount.getMoney()-money);tAccount.setMoney(tAccount.getMoney()money);//持久化到数据库accountDao.update(sAccount);//模拟异常发生int i1/0;accountDao.update(tAccount);}
} 5、测试转账业务
Test
public void test1(){//获得业务层对象AccountService service new AccountServiceImpl();service.transfer(aaa,bbb,100D);
} 二编写ConnectionUtils工具类管理数据库连接
public class ConnectionUtils {private ThreadLocalConnection tl new ThreadLocalConnection();private DataSource dataSource;public void setDataSource(DataSource dataSource) {this.dataSource dataSource;}/*** 获取当前线程上的连接* return*/public Connection getThreadConnection() {try{//1.先从ThreadLocal上获取Connection connection tl.get();//2.判断当前线程上是否有连接if (connection null) {//3.从数据源中获取一个连接并且存入ThreadLocal中connection dataSource.getConnection();tl.set(connection);}//4.返回当前线程上的连接return connection;}catch (Exception e){throw new RuntimeException(e);}}/*** 把连接和线程解绑*/public void removeConnection(){tl.remove();} 三编写事务管理工具类
/**
* 和事务管理相关的工具类它包含了开启事务提交事务回滚事务和释放连接
*/
public class TransactionManager {private ConnectionUtils connectionUtils;public void setConnectionUtils(ConnectionUtils connectionUtils) {this.connectionUtils connectionUtils;}/*** 开启事务*/public void beginTransaction(){try {connectionUtils.getThreadConnection().setAutoCommit(false);}catch (Exception e){e.printStackTrace();}}/*** 提交事务*/public void commit(){try {connectionUtils.getThreadConnection().commit();}catch (Exception e){e.printStackTrace();}}/*** 回滚事务*/public void rollback(){try {connectionUtils.getThreadConnection().rollback();}catch (Exception e){e.printStackTrace();}}/*** 释放连接*/public void release(){try {connectionUtils.removeConnection();connectionUtils.getThreadConnection().close();//还回连接池中}catch (Exception e){e.printStackTrace();}}
} 四编写业务层和持久层控制代码并配置Spring的IOC
public class AccountDaoImpl implements AccountDao {private QueryRunner queryRunner ;private ConnectionUtils connectionUtils;public void setQueryRunner(QueryRunner queryRunner) {this.queryRunner queryRunner;}public void setConnectionUtils(ConnectionUtils connectionUtils) {this.connectionUtils connectionUtils;}Overridepublic Account findByName(String name) {try {String sql select * from account where name ? ;Account account queryRunner.query(connectionUtils.getThreadConnection(), sql,new BeanHandlerAccount(Account.class), name);return account;} catch (SQLException throwables) {throwables.printStackTrace();}return null;}Overridepublic void update(Account account) {try {String sql update account set money ? where name ? ;queryRunner.update(connectionUtils.getThreadConnection(),sql,account.getMoney(),account.getName());} catch (SQLException throwables) {throwables.printStackTrace();}}
}
public class AccountServiceImpl implements AccountService {//依赖dao层private AccountDao accountDao ;private TransactionManager txManager;public AccountDao getAccountDao() {return accountDao;}public void setAccountDao(AccountDao accountDao) {this.accountDao accountDao;}public TransactionManager getTxManager() {return txManager;}public void setTxManager(TransactionManager txManager) {this.txManager txManager;}Overridepublic void transfer(String sourceAccountName, String targetAccountName,double money) {try {//开启事务txManager.beginTransaction();//查询来源账户和目标账户Account sAccount accountDao.findByName(sourceAccountName);Account tAccount accountDao.findByName(targetAccountName);//来源账户减钱目标账户加钱sAccount.setMoney(sAccount.getMoney()-money);tAccount.setMoney(tAccount.getMoney()money);//持久化到数据库accountDao.update(sAccount);//模拟异常发生int i1/0;accountDao.update(tAccount);} catch (Exception exception){//事务回滚txManager.rollback();exception.printStackTrace();} finally {//释放资源txManager.release();}}
}
!-- 配置数据源 --
bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSource!--连接数据库的必备信息--property namedriverClass valuecom.mysql.jdbc.Driver/propertyproperty namejdbcUrl valuejdbc:mysql://localhost:3306/test
/propertyproperty nameuser valueroot/propertyproperty namepassword valueroot/property
/bean!-- 配置Connection的工具类 ConnectionUtils --
bean idconnectionUtils classcom.offcn.utils.ConnectionUtils!-- 注入数据源--property namedataSource refdataSource/property
/bean!-- 配置事务管理器--
bean idtxManager classcom.offcn.utils.TransactionManager!-- 注入ConnectionUtils --property nameconnectionUtils refconnectionUtils/property
/bean!--配置QueryRunner--
bean idqueryRunner classorg.apache.commons.dbutils.QueryRunnerscopeprototype/bean!--配置Dao对象--
bean idaccountDao classcom.offcn.dao.impl.AccountDaoImpl!-- 注入QueryRunner --property namequeryRunner refqueryRunner/property!-- 注入ConnectionUtils --property nameconnectionUtils refconnectionUtils/property
/bean!-- 配置Service层对象 --
bean idaccountService classcom.offcn.service.impl.AccountServiceImpl!-- 注入dao --property nameaccountDao refaccountDao/property!--注入txManager--property nametxManager reftxManager/property
/bean 五测试转账
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(locations classpath:applicationContext.xml)
public class TestAccountTransfer {Autowiredprivate AccountService accountService;Testpublic void test1(){accountService.transfer(aaa,bbb,100);}
} 六转账业务案例中存在的问题 七使用动态代理实现事务控制
1、创建代理工具类
/**
* 用于创建客户业务层对象工厂当然也可以创建其他业务层对象只不过我们此处不做那么繁琐
*/
public class BeanFactory {private AccountService accountService;private TransactionManager txManager;public void setAccountService(AccountService accountService) {this.accountService accountService;}public void setTxManager(TransactionManager txManager) {this.txManager txManager;}/*** 获取Service代理对象* return*/public AccountService getAccountService() {return (AccountService)Proxy.newProxyInstance(accountService.getClass().getClassLoader(),accountService.getClass().getInterfaces(),new InvocationHandler() {/*** 添加事务的支持* param proxy* param method 执行目标方法被封装到Method当中* param args 执行目标方法的参数* return 执行目标方法的返回值* throws Throwable*/Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object returntValue null;try {//1.开启事务txManager.beginTransaction();//2.执行操作returntValue method.invoke(accountService, args);//3.提交事务txManager.commit();//4.返回结果return returntValue;} catch (Exception e) {//5.回滚操作txManager.rollback();throw new RuntimeException(e);} finally {//6.释放连接txManager.release();}}});}
}
2、配置并测试动态代理转账业务
配置静态工厂生产实例bean
!--配置beanfactory--
bean idbeanFactory classcom.offcn.factory.BeanFactory!-- 注入service --property nameaccountService refaccountService/property!-- 注入事务管理器 --property nametxManager reftxManager/property
/bean
!--配置代理的service--
bean idproxyAccountService factory-beanbeanFactory factorymethodgetAccountService
/bean
业务层代码的修改把和事务相关的代码去掉
Override
public void transfer(String sourceAccountName, String targetAccountName, double money) {Account sAccount accountDao.findByName(sourceAccountName);Account tAccount accountDao.findByName(targetAccountName);//来源账户减钱目标账户加钱sAccount.setMoney(sAccount.getMoney()-money);tAccount.setMoney(tAccount.getMoney()money);//持久化到数据库accountDao.update(sAccount);//模拟异常发生//int i1/0;accountDao.update(tAccount);
}
测试代码
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(locations classpath:applicationContext.xml)
public class TestAccountTransfer {AutowiredQualifier(proxyAccountService)private AccountService accountProxyService;Testpublic void testAccountProxy(){accountProxyService.transfer(aaa,bbb,100D);}
}
总结使用动态代理改造之后业务层代码已经和事务相关代码进行了分离并且保证了事务的一致性。 十三、SpringAOP机制详解 一AOP概述
1、什么是AOP
AOP为Aspect Oriented Programming的缩写意思为面向切面编程是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。 2、AOP编程思想
AOP面向切面编程是一种编程思想是OOP的延续是软件开发中的一个热点也是Spring框架中的一个重要内容是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离从而使得业务逻辑各个部分之间的耦合度降低提高程序的可重用性同时提高了开发的效率。 3、Spring中的常用术语
Joinpoint连接点所谓连接点是指那些被拦截到的点。在Spring中这些点指的是方法因为Spring只支持方法类型的连接点。Pointcut切入点所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。Advice通知/增强通知是指拦截到Joinpoint之后所要做的事情就是通知。通知的类型前置通知后置通知异常通知最终通知环绕通知。Introduction引介引介是一种特殊的通知在不修改类代码的前提下Introduction可以在运行期为类动态地添加一些方法。Target目标对象代理的目标对象。Proxy代理一个类被AOP织入增强后就产生一个结果代理类。Weaving织入是指把增强应用到目标对象来创建新的代理对象的过程。Spring采用动态代理织入而Aspect采用编译期织入和类装载期织入。Aspect切面是切入点和通知引介的结合。 4、AOP编程底层的实现机制
1JDK动态代理
只提供接口的代理不支持类的代理。JDK动态代理通过反射来接受被代理的类并且要求被代理的类必须实现一个接口。JDK动态代理的核心是invocationHandler接口和Proxy类 2CGLB动态代理
通过继承的方式来实现动态代理因此如果某个类被标记为final那么他是无法使用CGLB做动态代理。 5、AOP的作用及优势
作用在程序运行期间在不修改源码的情况下对方法进行功能增强。
优势减少重复代码提高开发效率并且便于维护。 二Spring基于XML的AOP配置
1、环境搭建
1添加依赖
propertiesspring.version5.2.5.RELEASE/spring.version
/propertiesdependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.8.7/version/dependency
/dependencies
2添加代码
准备实体类
public class Account implements Serializable {private Integer id;private String name;private double money;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public double getMoney() {return money;}public void setMoney(double money) {this.money money;}Overridepublic String toString() {return Account{ id id , name name \ , money money };}
}
创建AccountDao接口以及实现类
public interface AccountDao {public Account findByName(String name);public void update(Account account);
}
public class AccountDaoImpl implements AccountDao {private QueryRunner queryRunner new QueryRunner(new ComboPooledDataSource());Overridepublic Account findByName(String name) {try {String sql select *from account where name ? ;Account account queryRunner.query(sql, new BeanHandler(Account.class), name);return account;} catch (SQLException throwables) {throwables.printStackTrace();}return null;}Overridepublic void update(Account account) {try {String sql update account set money ? where name ? ;queryRunner.update(sql, account.getMoney(), account.getName());} catch (SQLException throwables) {throwables.printStackTrace();}}
}
创建AccountService接口以及实现类
public interface AccountService {
/**
* 定义业务方法 实现转账
* param sourceAccountName 来源账户
* param targetAccountName 目标账户
* param money 转账金额
*/
public void transfer(String sourceAccountName,String targetAccountName,double money);
}
public class AccountServiceImpl implements AccountService {//依赖dao层private AccountDao accountDao new AccountDaoImpl();Overridepublic void transfer(String sourceAccountName, String targetAccountName,double money) {//查询来源账户和目标账户Account sAccount accountDao.findByName(sourceAccountName);Account tAccount accountDao.findByName(targetAccountName);//来源账户减钱目标账户加钱sAccount.setMoney(sAccount.getMoney()-money);tAccount.setMoney(tAccount.getMoney()money);//持久化到数据库accountDao.update(sAccount);//模拟异常发生int i1/0;accountDao.update(tAccount);}
} 3创建配置文件并导入约束
?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd
/beans
4配置Spring的IOC
!-- 配置数据源 --
bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSource!--连接数据库的必备信息--property namedriverClass valuecom.mysql.jdbc.Driver/propertyproperty namejdbcUrl valuejdbc:mysql://localhost:3306/test
/propertyproperty nameuser valueroot/propertyproperty namepassword valueroot/property
/bean!-- 配置Connection的工具类 ConnectionUtils --
bean idconnectionUtils classcom.offcn.utils.ConnectionUtils!-- 注入数据源--property namedataSource refdataSource/property
/bean!--配置queryRunner--
bean idqueryRunner classorg.apache.commons.dbutils.QueryRunner/bean!--配置accountDao--
bean idaccountDao classcom.offcn.dao.impl.AccountDaoImplproperty namequeryRunner refqueryRunner/propertyproperty nameconnectionUtils refconnectionUtils/property
/bean!--配置accountService--
bean idaccountService classcom.offcn.service.impl.AccountServiceImplproperty nameaccountDao refaccountDao/property
/bean
5抽取公共代码制作成通知
/**
* 和事务管理相关的工具类它包含了开启事务提交事务回滚事务和释放连接
*/
public class TransactionManager {private ConnectionUtils connectionUtils;public void setConnectionUtils(ConnectionUtils connectionUtils) {this.connectionUtils connectionUtils;}/*** 开启事务*/public void beginTransaction(){try {connectionUtils.getThreadConnection().setAutoCommit(false);}catch (Exception e){e.printStackTrace();}}/*** 提交事务*/public void commit(){try {connectionUtils.getThreadConnection().commit();}catch (Exception e){e.printStackTrace();}}/*** 回滚事务*/public void rollback(){try {connectionUtils.getThreadConnection().rollback();}catch (Exception e){e.printStackTrace();}}/*** 释放连接*/public void release(){try {connectionUtils.removeConnection();connectionUtils.getThreadConnection().close();//还回连接池中}catch (Exception e){e.printStackTrace();}}
} 2、AOP配置步骤
1配置bean标签
!--配置通知txManager--
bean idtxManager classcom.offcn.utils.TransactionManagerproperty nameconnectionUtils refconnectionUtils/property
/bean 2使用aopconfig 声明AOP配置
aop:config: 作用 开始声明aop配置
aop:config!-- 配置的代码都写在此处 --
/aop:config 3使用aopaspect 配置切面
aopaspect 作用 用于配置切面 属性id 给切面提供一个唯一标识。 ref引用配置好的通知类 bean 的 id。
aop:aspect idtdAdvice reftxManager!--配置通知的类型要写在此处--
/aop:aspect 4使用aoppointcut配置切入点表达式
aop:pointcut 作用 用于配置切入点表达式。就是指定对哪些类的哪些方法进行增强。 属性 expression用于定义切入点表达式。 id用于给切入点表达式提供一个唯一标识
aop:pointcut idpoint1 expressionexecution( public void com.offcn.service.impl.AccountServiceImpl.transfer(java.lang.String,java.lang.St
ring,java.lang.Double))/ 5使用aopxxx配置对应的通知类型 aopbefore 作用用于指定通知类中的增强方法名称 属性method用于指定通知类中的增强方法名称 ponitcut-ref用于指定切入点的表达式的引用 poinitcut用于指定切入点表达式 执行时间点切入点方法执行之前执行
aop:before methodbeginTransaction pointcut-refpoint1/aop:before aopafter-returning 作用用于配置后置通知 属性method指定通知中方法的名称 pointct定义切入点表达式 pointcut-ref指定切入点表达式的引用 执行时间点切入点方法正常执行之后。它和异常通知只能有一个执行。
aop:after-returning methodcommit pointcut-refpoint1/ aopafter-throwing 作用用于配置异常通知 属性method指定通知中方法的名称 pointct定义切入点表达式 pointcut-ref指定切入点表达式的引用 执行时间点切入点方法执行产生异常后执行。它和后置通知只能执行一个。
aop:after-throwing methodrollback pointcut-refpoint1/ aopafter 作用用于配置最终通知 属性method指定通知中方法的名称 pointct定义切入点表达式 pointcut-ref指定切入点表达式的引用 执行时间点无论切入点方法执行时是否有异常它都会在其后面执行。
aop:after methodrelease pointcut-refpoint1/ 3、切入点表达式说明
切入点表达式的语法
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
访问修饰符可以省略返回值类型、包名、类名、方法名可以使用*代表任意包名与类名之间一个点。代表当前包下的类两个点...表示当前包及其子包下的类参数列表可以使用两个点...表示任意个数任意类型的参数列表 4、环绕通知配置事务管理
在TransactionManager类当中添加方法
/*** 环绕通知:* spring 框架为我们提供了一个接口ProceedingJoinPoint它可以作为环绕通知的方法参
数。* 在环绕通知执行时spring 框架会为我们提供该接口的实现类对象我们直接使用就行。* param pjp* return
*/
public Object transactionAround(ProceedingJoinPoint pjp) {//定义返回值Object returnValue null;try {//获取方法执行所需的参数Object[] args pjp.getArgs();//前置通知开启事务beginTransaction();//执行方法returnValue pjp.proceed(args);//后置通知提交事务commit();}catch(Throwable e) {//异常通知回滚事务rollback();e.printStackTrace();}finally {//最终通知释放资源release();}return returnValue;
}
aoparound 作用用于配置环绕通知 属性method指定通知中方法的名称 pointct定义切入点表达式 pointcut-ref指定切入点表达式的引用 说明它是 spring 框架为我们提供的一种可以在代码中手动控制增强代码什么时候执行的方式。 注意通常情况下环绕通知都是独立使用的。
aop:configaop:aspect idtdAdvice reftxManageraop:pointcut idpoint1 expressionexecution(*com.offcn.service.impl.*.*(..))/!-- 配置环绕通知 --aop:around methodtransactionAround pointcut-refpoint1//aop:aspect
/aop:config 三Spring基于注解的AOP配置
1、环境搭建
1构建maven工程添加AOP注解的相关依赖
propertiesspring.version5.2.5.RELEASE/spring.version
/propertiesdependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.8.7/version/dependency
/dependencies 2导入代码
沿用上一章节资源
copy Account AccountDao AccountDaoImpl AccountService AccountServiceImpl 3在配置文件中导入context的名称空间且配置
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:aophttp://www.springframework.org/schema/aopxmlns:contexthttp://www.springframework.org/schema/contextxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd
/beans 4资源使用注解配置
!-- 配置数据源 --
bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSource!--连接数据库的必备信息--property namedriverClass valuecom.mysql.jdbc.Driver/propertyproperty namejdbcUrl valuejdbc:mysql://localhost:3306/test
/propertyproperty nameuser valueroot/propertyproperty namepassword valueroot/property
/bean!--配置queryRunner--bean idqueryRunner classorg.apache.commons.dbutils.QueryRunner
/bean 5在配置文件中指定spring要扫描的包
!-- 告知 spring在创建容器时要扫描的包 --
context:component-scan base-packagecom.offcn/context:component-scan 2、配置步骤
1通知类使用注解配置
/**
* 和事务管理相关的工具类它包含了开启事务提交事务回滚事务和释放连接
*/
Component(txManager)
public class TransactionManager {Autowiredprivate ConnectionUtils connectionUtils;
} 2通知类使用Aspect注解声明为切面
/**
* 和事务管理相关的工具类它包含了开启事务提交事务回滚事务和释放连接
*/
Component(txManager)
Aspect //表明当前类是一个切面类
public class TransactionManager {Autowiredprivate ConnectionUtils connectionUtils;
} 3增强方法上使用注解配置通知
Before 作用把当前方法看成是前置通知 属性value用于指定切入点表达式还可以指定切入点表达式的引用。
//开启事务
Before(execution(* com.offcn.service.impl.*.*(..))))
public void beginTransaction(){try {System.out.println(before..........................);connectionUtils.getThreadConnection().setAutoCommit(false);}catch (Exception e){e.printStackTrace();}
} AfterReturning 作用把当前方法看成是后置通知。 属性value用于指定切入点表达式还可以指定切入点表达式的引用
// 提交事务
AfterReturning(execution(* com.offcn.service.impl.*.*(..))))
public void commit(){try {connectionUtils.getThreadConnection().commit();}catch (Exception e){e.printStackTrace();}
} AfterThrowing 作用把当前方法看成是异常通知。 属性value用于指定切入点表达式还可以指定切入点表达式的引用
//回滚事务
AfterThrowing(execution(* com.offcn.service.impl.*.*(..))))
public void rollback(){try {connectionUtils.getThreadConnection().rollback();}catch (Exception e){e.printStackTrace();}
} After 作用把当前方法看成是最终通知。 属性value用于指定切入点表达式还可以指定切入点表达式的引用 。
//释放连接
After(execution(* com.offcn.service.impl.*.*(..))))
public void release(){try {connectionUtils.removeConnection();connectionUtils.getThreadConnection().close();//还回连接池中}catch (Exception e){e.printStackTrace();}
} 4开启Spring对注解AOP的支持
!-- 开启 spring 对注解 AOP 的支持 --
aop:aspectj-autoproxy/ 5环绕通知注解配置
Around
作用把当前方法看成是环绕通知。
属性value用于指定切入点表达式还可以指定切入点表达式的引用。
// 环绕通知:
Around(execution(*com.offcn.service.impl.*.*(..)))
public Object transactionAround(ProceedingJoinPoint pjp) {//定义返回值Object returnValue null;try {//获取方法执行所需的参数Object[] args pjp.getArgs();//前置通知开启事务beginTransaction();//执行方法returnValue pjp.proceed(args);//后置通知提交事务commit();}catch(Throwable e) {//异常通知回滚事务rollback();e.printStackTrace();}finally {//最终通知释放资源release();}return returnValue;
} 6切入点表达式注解
Pointcut(execution(* com.offcn.service.impl.*.*(..)))
private void point1() {}// 环绕通知:
Around(point1())///注意千万别忘了写括号
public Object transactionAround(ProceedingJoinPoint pjp) {//定义返回值Object returnValue null;try {//获取方法执行所需的参数Object[] args pjp.getArgs();//前置通知开启事务beginTransaction();//执行方法returnValue pjp.proceed(args);//后置通知提交事务commit();}catch(Throwable e) {//异常通知回滚事务rollback();e.printStackTrace();}finally {//最终通知释放资源release();}return returnValue;
} 十四、Spring事务详解
一Spring基于XML的事务配置
1、环境搭建
1构建工程添加依赖
propertiesspring.version5.2.5.RELEASE/spring.version
/propertiesdependencies!--导入junit单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!--导入spring的context坐标--dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion${spring.version}/version/dependency!--导入Jdbc模块依赖--dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion${spring.version}/version/dependency!--导入Mysql 驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency!--导入C3P0连接池--dependencygroupIdcom.mchange/groupIdartifactIdc3p0/artifactIdversion0.9.5.2/version/dependency!--aop--dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.8.7/version/dependency
/dependencies 2创建Spring的配置文件导入约束
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd!-- 告知 spring在创建容器时要扫描的包 --context:component-scan base-packagecom.offcn/context:component-scan!-- 配置数据源 --bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSource!--连接数据库的必备信息--property namedriverClass valuecom.mysql.jdbc.Driver/propertyproperty namejdbcUrl valuejdbc:mysql://localhost:3306/test
/propertyproperty nameuser valueroot/propertyproperty namepassword valueroot/property
/bean!--JdbcTemplate--bean idjdbcTemplate classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean
/beans 3沿用转账业务
copy Account AccountDao AccountDaoImpl AccontService AccountServiceImpl 代码 注意 AccountDaoImpl 具体使用使用Spring提供的JdbcTemplate模板对象实现 Repository(accountDao)
public class AccountDaoImpl implements AccountDao {Autowiredprivate JdbcTemplate jdbcTemplate;Overridepublic Account findByName(String name) {String sql select * from account where name ? ;Account account this.jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(Account.class), name);return account;}Overridepublic void update(Account account) {String sql update account set money ? where name ? ;this.jdbcTemplate.update(sql, account.getMoney(), account.getName());}
} 2、事务管理配置步骤
1配置事务管理器
!--平台事务管理器--
bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property
/bean 2配置事务的通知引用事务管理器
!--事务的配置--
tx:advice idtxAdvice transaction-managertransactionManager
/tx:advice 3配置事务的属性
!--指定方法名称是业务核心方法read-only是否是只读事务。默认 false不只读。isolation指定事务的隔离级别。默认值是使用数据库的默认隔离级别。propagation指定事务的传播行为。timeout指定超时时间。默认值为-1。永不超时。rollback-for用于指定一个异常当执行产生该异常时事务回滚。产生其他异常事务不回滚。没有默认值任何异常都回滚。no-rollback-for用于指定一个异常当产生该异常时事务不回滚产生其他异常时事务回滚。没有默认值任何异常都回滚。
--
tx:attributestx:method name*/
/tx:attributes 4配置AOP切入点表达式
!--事务的aop增强--
aop:configaop:pointcut idmyPointcut expressionexecution(*com.offcn.service.impl.*.*(..))/
/aop:config 5配置切入点表达式和事务通知的对应关系
!--在aopconfig标签内部建立事务的通知和切入点表达式的关系--
aop:advisor advice-reftxAdvice pointcut-refmyPointcut/aop:advisor 二Spring基于注解的事务配置 1、环境搭建
1构建maven工程添加相关依赖
propertiesspring.version5.2.5.RELEASE/spring.version
/propertiesdependencies!--导入junit单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!--导入spring的context坐标--dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion${spring.version}/version/dependency!--导入Jdbc模块依赖--dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion${spring.version}/version/dependency!--导入Mysql 驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency!--导入C3P0连接池--dependencygroupIdcom.mchange/groupIdartifactIdc3p0/artifactIdversion0.9.5.2/version/dependency!--aop--dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.8.7/version/dependency
/dependencies 2创建Spring配置文件
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aopxmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd!-- 告知 spring在创建容器时要扫描的包 --context:component-scan base-packagecom.offcn/context:component-scan!-- 配置数据源 --bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSource!--连接数据库的必备信息--property namedriverClass valuecom.mysql.jdbc.Driver/propertyproperty namejdbcUrl valuejdbc:mysql://localhost:3306/test
/propertyproperty nameuser valueroot/propertyproperty namepassword valueroot/property/bean!--JdbcTemplate--bean idjdbcTemplate classorg.springframework.jdbc.core.JdbcTemplateproperty namedataSource refdataSource/property/bean
/beans 3沿用转账业务的代码dao实现类和service实现类采用注解的形式添加到容
器中管理
copy Account AccountDao AccountImpl AccountService AccountServiceImpl 到工程当中复用 2、事务管理配置步骤
1配置事务管理器并注入数据源
!-- 配置事务管理器 --
bean idtransactionManagerclassorg.springframework.jdbc.datasource.DataSourceTran
sactionManagerproperty namedataSource refdataSource/property
/bean 2在业务层使用Transactional注解
/**
该注解的属性和 xml 中的属性含义一致。该注解可以出现在接口上类上和方法上。
出现接口上表示该接口的所有实现类都有事务支持。
出现在类上表示类中所有方法有事务支持
出现在方法上表示方法有事务支持。
以上三个位置的优先级方法类接口
*/Service(accountService)
Transactional(readOnly true,propagation Propagation.SUPPORTS)
public class AccountServiceImpl implements AccountService {//依赖dao层Autowiredprivate AccountDao accountDao ;Transactional(readOnly false,propagation Propagation.REQUIRED)Overridepublic void transfer(String sourceAccountName, String targetAccountName,Double money) {Account sAccount accountDao.findByName(sourceAccountName);Account tAccount accountDao.findByName(targetAccountName);//来源账户减钱目标账户加钱sAccount.setMoney(sAccount.getMoney()-money);tAccount.setMoney(tAccount.getMoney()money);//持久化到数据库accountDao.update(sAccount);//模拟异常发生//int i1/0;accountDao.update(tAccount);}
} 3配置文件中开启Spring对注解事务的支持
!-- 开启 spring 对注解事务的支持 --
tx:annotation-driven transaction-managertransactionManager/ 十五、Spring整合Mybatis实现用户的CRUD
一整理思路分析
Mybatis框架是一个持久层ORM框架而Spring则是一个综合性一站式框架。所以整合是Mybatis往Spring上整合。就是让Spring框架接管Mybatis的组件。 Mybatis 单独运行时数据源的管理事务的管理 SqlSessionFactory 以及接口的实现类都是 Mybatis管理的整合后以上组件交给Spring 管理。 二构建maven工程添加依赖
propertiesspring.version5.2.5.RELEASE/spring.version
/propertiesdependencies!--导入junit单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!--导入spring的context坐标--dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion${spring.version}/version/dependency!--导入Jdbc模块依赖--dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion${spring.version}/version/dependency!--导入Mysql 驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency!--导入C3P0连接池--dependencygroupIdcom.mchange/groupIdartifactIdc3p0/artifactIdversion0.9.5.2/version/dependency!--aop--dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.8.7/version/dependency!--mybatis-Spring适配包 --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion2.0.0/version/dependency!-- mybatis orm框架 --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.4.6/version/dependency/dependencies 三构建数据库表并创建实体类
create table User(
id int primary key auto_increment,
name varchar(32) not null,
address varchar(32) not null,
birthday date
);
public class User implements Serializable {private Integer id;private String name;private String address;private Date birthday;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public String getAddress() {return address;}public void setAddress(String address) {this.address address;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday birthday;}Overridepublic String toString() {return User{ id id , name name \ , address address \ , birthday birthday };}
} 四编写dao层的接口UserMapper
public interface UserMapper {int insert(User user);int update(User user);int delete(Integer id);User findById(Integer id);ListUser findAll();
} 五构建mapper接口对应的sql配置文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.offcn.mapper.UserMapperresultMap idBaseResultMap typecom.offcn.pojo.Userid columnid jdbcTypeINTEGER propertyid /result columnname jdbcTypeVARCHAR propertyname /result columnaddress jdbcTypeVARCHAR propertyaddress /result columnbirthday jdbcTypeDATE propertybirthday //resultMapinsert idinsert parameterTypecom.offcn.pojo.Userinsert into user (name, birthday, address)values (#{name}, #{birthday},#{address})/insertupdate idupdateupdate usersetname #{name},birthday#{birthday},address #{address}where id#{id}/updatedelete iddeletedelete from userwhere id #{id}/deleteselect idfindById resultMapBaseResultMapselect * from user where id#{id}/selectselect idfindAll resultMapBaseResultMapselect * from user/select
/mapper 六构建服务层接口UserService
public interface UserService {int insert(User user);int update(User user);int delete(Integer id);User findById(Integer id);ListUser findAll();
} 七构建服务层实现类UserServiceImpl
Service
public class UserServiceImpl implements UserService {Autowiredprivate UserMapper userMapper;Overridepublic int insert(User user) {int num userMapper.insert(user);return num;}Overridepublic int update(User user) {int num userMapper.update(user);return num;}Overridepublic int delete(Integer id) {int num userMapper.delete(id);return num;}Overridepublic User findById(Integer id) {User user userMapper.findById(id);return user;}Overridepublic ListUser findAll() {ListUser userList userMapper.findAll();return userList;}
} 八构建配置文件
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxmlns:txhttp://www.springframework.org/schema/txxmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!--开启包扫描--context:component-scan base-packagecom.offcn /context:component-scan!-- 配置数据源 --bean iddataSource classcom.mchange.v2.c3p0.ComboPooledDataSource!--连接数据库的必备信息--property namedriverClass valuecom.mysql.jdbc.Driver/propertyproperty namejdbcUrl valuejdbc:mysql://localhost:3306/test
/propertyproperty nameuser valueroot/propertyproperty namepassword valueroot/property/bean!--Mybatis 核心对象 工厂对象--bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean!--工厂创建必须注入一个数据源--property namedataSource refdataSource/!--指定mapper文件位置--property namemapperLocations valueclasspath:com/offcn/mapper/*Mapper.xml/property!--引入Mybatis的核心配置文件如果Mybaits的核心配置要保留需要再此处配置--property nameconfigLocation valueclasspath:SqlMapConfig.xml/!--别名配置--property nametypeAliasesPackage valuecom/offcn/pojo/!--进行分页插件的配置--property namepluginsarraybean classcom.github.pagehelper.PageInterceptorproperty namepropertiesvaluehelperDialectMySQLreasonabletruesupportMethodsArgumentstrueparamscountcountSqlautoRuntimeDialecttrue/value/property/bean/array/property/bean!--配置接口的扫描--bean idmapperScannerConfigurer classorg.mybatis.spring.mapper.MapperScannerConfigurer!--指定了包 能够将包下的接口生成实现类 --property namebasePackage valuecom.offcn.mapper/property/bean!--配置平台管理器--bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager!--注入数据源--property namedataSource refdataSource//beantx:annotation-driven transaction-managertransactionManager/
/beans 九测试代码
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(locations classpath:applicationContext.xml)
public class TestAccountTransfer {Autowiredprivate UserService userService;//saveTestpublic void testInsert(){User user new User();user.setName(admin);user.setAddress(china);user.setBirthday(new Date());int num userService.insert(user);System.out.println(num:num);}//updateTestpublic void testUpdate(){User user new User();user.setName(marry);user.setAddress(America);user.setBirthday(new Date());user.setId(1);int num userService.update(user);System.out.println(num:num);}//delete:Testpublic void testDelete(){int num userService.delete(1);System.out.println(num:num);}//findByIdTestpublic void testFindById(){User user userService.findById(2);System.out.println(user:user);}//findAllTestpublic void testFindByAll(){ListUser userList userService.findAll();System.out.println(userList:userList);}
}