Spring(四)——AOP、Spring实现AOP、Spring整合Mybatis、Spring中的事务管理
文章目录
- 1. 什么是AOP
- 2. 使用Spring实现AOP
- 2.1 使用Spring的API 接口实现
- 2.2 自定义实现
- 2.3 使用注解实现
- 3. 整合MyBatis
- 3.1 MyBatis-Spring简述
- 3.2 知识基础
- 3.3 整合mybatis的测试
- 4. 事务
- 4.1 回顾事务
- 4.2 spring中的事务管理
- 4.3 事务的测试
1. 什么是AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
不影响原来的业务情况下,动态新增功能。
2. 使用Spring实现AOP
2.1 使用Spring的API 接口实现
主要SpringAPI接口实现
(1)创建一个新maven项目,导入pom依赖
pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zz</groupId><artifactId>spring03</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.9.RELEASE</version></dependency><!-- AOP的织入包 --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>
</dependencies></project>
(2)创建一个接口,创建一个接口的实现类
UserService接口:
package com.zz.service;
//用户业务层
public interface UserService {public void add();public void delete();public void update();public void search();
}
UserServiceImpl 接口实现类:
package com.zz.service.impl;import com.zz.service.UserService;public class UserServiceImpl implements UserService {public void add() {System.out.println("增加用户");}public void delete() {System.out.println("删除用户");}public void update() {System.out.println("更新用户");}public void search() {System.out.println("查询用户");}
}
(3)创建两个增加类(前置,后置)
Log 日志增强类(前置):
package com.zz.config;
//日志增强类 前置
import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class Log implements MethodBeforeAdvice {public void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了");}
}
LogAfter日志增强类(后置):
package com.zz.config;
//日志增强类 后置
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;public class LogAfter implements AfterReturningAdvice {public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName()+"的"+method.getName()+"方法返回了"+returnValue);}
}
(4)在applicationContext.xml文件中配置增强类实现增强:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="userService" class="com.zz.service.impl.UserServiceImpl"/><bean id="log" class="com.zz.config.Log"/><bean id="afterlog" class="com.zz.config.LogAfter"/><!--aop的配置方式一:配置增强类--><aop:config><!--切入点,哪些方法需要增强expression 表达式是类名的全称,确定到实现类中的方法--><aop:pointcut id="pc-userservice" expression="execution(* com.zz.service.impl.UserServiceImpl.*(..))"/><!--环绕 即将UserServiceImpl中的所有方法做前置和后置增强--><aop:advisor advice-ref="log" pointcut-ref="pc-userservice"/><aop:advisor advice-ref="afterlog" pointcut-ref="pc-userservice"/></aop:config></beans>
(5)Test 测试类:
import com.zz.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;//客户端
public class MyTest {@Testpublic void test1(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService) context.getBean("userService");userService.add();}
}
测试结果:
2.2 自定义实现
主要是切面定义,切面就是一个类
(1)创建一个自定义类 DiyPointCut:
package com.zz.config;
//自定义类 /增强类/切面
public class DiyPointCut {public void before(){System.out.println("=====方法执行前=====");}public void after(){System.out.println("=====方法执行后=====");}
}
(2)在applicationContext.xml文件中配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="diy" class="com.zz.config.DiyPointCut"/><!--aop的配置方式二:配置增切面--><aop:config><aop:aspect ref="diy"><aop:pointcut id="pc-userservice" expression="execution(* com.zz.service.impl.UserServiceImpl.*(..))"/><aop:before method="before" pointcut-ref="pc-userservice"/><aop:after method="after" pointcut-ref="pc-userservice"/></aop:aspect></aop:config>
</beans>
(3)Test 测试类:
代码与上面相同
测试结果:
2.3 使用注解实现
(1)创建一个类 AnnotationPointCut
package com.zz.config;import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;//注解实现增强,切面原理
@Aspect
public class AnnotationPointCut {@Before("execution(* com.zz.service.impl.UserServiceImpl.*(..))")public void before(){System.out.println("=====方法执行前=====");}@After("execution(* com.zz.service.impl.UserServiceImpl.*(..))")public void after(){System.out.println("=====方法执行后=====");}
}
(2)在applicationContext.xml文件中配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="annotationPointCut" class="com.zz.config.AnnotationPointCut"/><!--aop的配置方式三:使用注解实现增强类--><!--让spring识别注解,一定要添加--><aop:aspectj-autoproxy/>
</beans>
(3)Test 测试类:
代码与上面相同
测试结果:
3. 整合MyBatis
参考学习网站:http://mybatis.org/spring/zh/index.html
3.1 MyBatis-Spring简述
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
3.2 知识基础
在开始使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 这两个框架和有关它们的术语。这很重要——因为本手册中不会提供二者的基本内容,安装和配置教程。
MyBatis-Spring 需要以下版本:配套
3.3 整合mybatis的测试
目录:
(1)在pom.xml文件中导入所有依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zz</groupId><artifactId>spring04</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.10.RELEASE</version></dependency><!--Spring jdbc(new)--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.10.RELEASE</version></dependency><!--aop aspectjweaver--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency><!--mybatis-spring--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.2</version></dependency></dependencies><!-- 如果xml在java文件下,就要设置资源过滤--><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources></build></project>
(2)实体类User:
对应MySQL数据库里的user表
package com.zz.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private int id;private String name;private String pwd;
}
(3)UserMapper接口:
package com.zz.mapper;import com.zz.pojo.User;import java.util.List;public interface UserMapper {public List<User> getUserList();}
(4)接口的实现类UserMapperImpl:
package com.zz.mapper.impl;import com.zz.mapper.UserMapper;
import com.zz.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;import java.util.List;public class UserMapperImpl implements UserMapper {//注入sqlSessionprivate SqlSessionTemplate sqlSession ;public void setSqlSession(SqlSessionTemplate sqlSession) {this.sqlSession=sqlSession;}public List<User> getUserList(){UserMapper mapper = sqlSession.getMapper(UserMapper.class);return mapper.getUserList();}
}
(5)接口的配置文件UserMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zz.mapper.UserMapper"><select id="getUserList" resultType="User">select * from user</select>
</mapper>
(6)配置文件applicationContext.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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><!--1.数据源整合--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis? useUnicode=true&characterEncoding=utf8&useSSL=false"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--2. 注入sqlSessionFactory--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><!--扫描包--><property name="typeAliasesPackage" value="com.zz.pojo"/><property name="mapperLocations" value="classpath:com/zz/mapper/xml/*.xml"/></bean><!--3.创建sqlSession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg index="0" ref="sqlSessionFactory"/></bean><!--4. 将sqlSession放入Bean中--><bean id="userMapperImpl" class="com.zz.mapper.impl.UserMapperImpl"><property name="sqlSession" ref="sqlSession"/></bean>
</beans>
(7)测试类MyTest:
import com.zz.mapper.UserMapper;
import com.zz.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {@Testpublic void test1(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserMapper userMapperImpl = (UserMapper) context.getBean("userMapperImpl");for (User user : userMapperImpl.getUserList()) {System.out.println(user);}}
}
测试结果:
4. 事务
4.1 回顾事务
- 把一组业务当成一个业务来做;要么都成功,要么都失败!
- 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!
- 确保完整性和一致性
事务ACID原则:
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中!
4.2 spring中的事务管理
- 声明式事务 : AOP
- 编程式事务: 需要再代码中,进行事务的管理
思考:
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况下;
- 如果我们不在SPRING中去配置声明式事务,我们就需要在代码中手动配置事务!
- 事务在项目的开发中十分重要,设计到数据的一致性和完整性问题,不容马虎!
4.3 事务的测试
(1)在UserMapper接口中加入两个方法
//添加事务int addUser(User user);//删除用户int deleteUser(int id);
(2)在接口的配置文件UserMapper.xml中编写对应的sql语句
注意:故意将删除语句写错,写为deletes
<insert id="addUser" parameterType="User">insert into user (id,name,pwd) values (#{id},#{name},#{pwd});</insert><delete id="deleteUser" parameterType="int">deletes from user where id=#{id}</delete>
(3)在接口的实现类UserMapperImpl中重写方法
package com.zz.mapper.impl;import com.zz.mapper.UserMapper;
import com.zz.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;import java.util.List;public class UserMapperImpl implements UserMapper {//注入sqlSessionprivate SqlSessionTemplate sqlSession ;public void setSqlSession(SqlSessionTemplate sqlSession) {this.sqlSession=sqlSession;}public List<User> getUserList(){UserMapper mapper = sqlSession.getMapper(UserMapper.class);//错误操作User user = new User(4,"小丽","123456");mapper.addUser(user);mapper.deleteUser(3); //sql存在错误return mapper.getUserList();}public int addUser(User user) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);return mapper.addUser(user);}public int deleteUser(int id) {UserMapper mapper = sqlSession.getMapper(UserMapper.class);return mapper.deleteUser(id);}
}
(4)其他代码与上面均不变,进行测试,并分析测试结果
发现控制台结果确实报错,但是点开MySQL,刷新user表,发现添加4号用户成功,删除3号用户失败。
这在实际的应用中,显然是不满足要求的,我们必须加入事务,使它符合事务的原则,让一组操作保证同时成功或同时失败!
(5)在applicationContext.xml中添加事务配置
导入事务tx和aop的命名空间:
还添加如下配置:
<!--整合事务--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-arg ref="dataSource" /></bean><!-- 事务配置增强(一个连接 aop,一个练连接transactionManager ) --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--propagation事务的传播特性--><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice><!-- AOP配置 --><aop:config><aop:pointcut id="txPointCut" expression="execution(* com.zz.mapper.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config>
(6)再次测试(此时还未改正sql语句)
发现控制台结果报错,再点开MySQL,刷新user表,发现添加用户和删除用户均失败。
(7)最后将删除用户的sql语句改正正确,再次测试
发现添加用户和删除用户均正确,控制台和数据库user列表显示完全一致!
Spring(四)——AOP、Spring实现AOP、Spring整合Mybatis、Spring中的事务管理相关推荐
- Java开发【Spring之AOP详解(xml--注解->方法增强、事务管理(声明事务的实现))】
文章目录 引入 一.AOP概述 1.什么是AOP 2.AOP的优势及使用场景 3.AOP实现原理 二.代理模式 1.代理模式概念 2.代理模式分类 3.静态代理演示 定义HouseAgencyComp ...
- spring Boot 2 基础篇 。内含 整合一个spring boot 的 小案例
目录 springBoot2基础篇 前言与开发环境 一.快速创建Boot项目 1.使用spring提供的快速构建 2.基于maven的手动构建 3.在Idea中隐藏指定文件/文件夹 二.SpringB ...
- Spring中的事务管理详解
在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...
- spring+mybatis之声明式事务管理初识(小实例)
前几篇的文章都只是初步学习spring和mybatis框架,所写的实例也都非常简单,所进行的数据访问控制也都很简单,没有加入事务管理.这篇文章将初步接触事务管理. 1.事务管理 理解事务管理之前,先通 ...
- spring事务管理器的作用_【面试必问】Spring中的事务管理详解
在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...
- 基于Spring中的事务管理机制
什么是事务? 通俗理解,事务其实就是一系列指令的集合. 为什么要使用事务管理? 我们在实际业务场景中,经常会遇到数据频繁修改读取的问题.在同一时刻,不同的业务逻辑对同一个表数据进行修改,这种冲突很可能 ...
- Spring中进行事务管理的两种方式
1.Spring中事务管理的API 事务是指逻辑上要么全部成功.要么全部失败的一组操作.例如用户A给用户B转账,则用户A账户余额减少.用户B账户增加这两个操作就是一组事务,必须全部成功或失败撤回操作, ...
- SpringBoot整合Mybatis,并实现事务控制
SpringBoot整合Mybatis,并实现事务控制 1. 在pom文件里添加相关maven文件 <parent><groupId>org.springframework.b ...
- 整合mybatis+spring项目。
目录 使用环境 MySQL Maven Mybatis 配置文件(非常重要) Spring 整体结构 测试 使用环境 jdk1.8 MySQ5.6 Maven3.3.6 MySQL 创建一个user表 ...
最新文章
- win10 error LNK1112: 模块计算机类型“X86”与目标计算机类型“x64”冲突
- word文档内容如何防止被复制
- Linux下源码安装CodeBlocks
- Delphi如果要追赶C#,最应该做的
- Start here: portal to the lectures
- free: seconds argument `1‘ failed
- 棋牌游戏服务器架构: 部署
- sql server 2008安装错误(无法处理异常)
- CUBA平台–用于快速应用程序开发的开源Java框架
- 管理R包——Pacman包介绍
- 虚拟内存和swap分区的关系
- SCSI 设备热插拔
- 力克亮相CISMA 2017,以工业4.0思维应对时尚变革
- python随机抽号_Python学习随记 ————随机抽号器(一)
- npcap关闭_npcap是什么软件
- 趣头条的区块链实验:为何金币贬值了6.6倍?
- C#酒店客房管理系统设计与实现
- 计算机算法基础_如何自学计算机专业
- 虚拟筛选及其方法学验证与ROC曲线python实现
- php 编写桌面程序_PHP能开发桌面应用吗?
热门文章
- BZOJ-3190-赛车-JLOI2013-暴力枚举
- uva5984(简单计算几何)
- BZOJ 4814 Luogu P3699 [CQOI2017]小Q的草稿 (计算几何、扫描线、set)
- arp 不同网段 相同vlan_ARP工作原理,相同网段和不同网段通信过程,代理ARP和ARP的区别,MAC地址为什么不能用来寻址...
- 电脑重启后python导入的库不见_为什么python不会在启动时自动导入每个模块?
- JavaScript原始类型转换和进制转换
- Vulhub搭建小记
- 新建maven项目更改 web版本
- We will be discontinuing the Nitrous Development Platform and Cloud IDE on November 14th, 2016.
- WSS 扩展文件夹的属性--如何给文件夹添加扩展字段