Spring整合MyBatis实战:从配置到CRUD完整指南
作为一名在Java开发道路上不断探索的开发者,我深知学习SSM框架的不易。在这个过程中,我经历了无数的挫折和困惑,但也收获了满满的成就感。为了帮助更多开发者顺利跨越这些障碍,我将自己的学习经验和实战技巧整理成这份学习笔记,希望能为你照亮前行的道路。
这份笔记从基础概念讲起,逐步深入到实际应用。从Spring的IoC和DI机制,到Bean的生命周期管理;从注解的灵活运用,到Spring与MyBatis的无缝整合;从AOP面向切面编程的实战应用,到事务管理的精细控制,每一个知识点都配有详细的代码示例和实战技巧,确保你能快速理解和应用。
一、基础知识
1.1、IOC
作用:控制反转
原理:每一次实例化对象时,都需要通过所需要的类名进行实例化,不方便代码,IOC就是设置一个中间的程序,让代码需要实例化时调用中间的程序(内部资源),通过内部资源进行
1、导入spring-conterxt依赖(maven刷新)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.5</version>
</dependency>
</dependencies>
2、创造daoy与service方法
3、设置xml方法
xml为spring资源类中进行设置的
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="bookservice" class="service.impl.bookserviceimpl"></bean>
<bean id="bookdao" class="dao.impl.bookdaoimpl"></bean>
</beans>
bean中进行设置,第一个属性为自己所取的名字,第二个为类所在的地址
4、程序的运行
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
bookservice bookservice = (service.bookservice) applicationContext.getBean("bookservice");
bookservice.service();
1.2、DI
作用:依赖注入
原理:在服务器中不用实例化对象,通过set的方法来获取,将dao与service进行结合,不用在service中再new对象
1、删除服务器中的new部分内容,改为set注入
private bookdao bookdao;
public void service(){
System.out.println("book service save......");
bookdao.service();
}
public void setBookdao(dao.bookdao bookdao) {
this.bookdao = bookdao;
}
2、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" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="bookservice" class="service.impl.bookserviceimpl">
<!--配置server与dao的关系-->
<!--property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean
-->
<property name="bookdao" ref="bookdao"></property>
</bean>
<bean id="bookdao" class="dao.impl.bookdaoimpl"></bean>
</beans>
name表示service中的名字,ref表示这里的名字
二、bean类型
2.1、bean的基础类型
1、name
可以设置别名,相当于id的作用,可以设置多个,后面的ref也可以引用name中的名字
<bean id="bookdao" name="dao book se" class="dao.impl.bookdaoimpl"/>
2、scope
单例和非单例的设置,具体表现在重新创立时是否会刷新一个新的地址,(默认为单例)
ApplicationContext cs = new ClassPathXmlApplicationContext("application.xml");
//获取bean
bookdao bookdao = (bookdao)cs.getBean("bookdao");
bookdao.service();
System.out.println(bookdao);
bookdao bookdao1 = (bookdao)cs.getBean("dao");
System.out.println(bookdao1);
名字不一样是name的原因
scope为singleton时为单例(默认)
scope为prototype时为多例
<bean id="bookservice" class="service.impl.bookserviceimpl" scope="prototype">
2.2、bean的实例化
创建bean使用构造方法来完成
1、构造方法实例化
通过反射的原理(直接通过class类进行)直接进行访问构造函数,无论是公共还是私有都能强制进行访问,不能设置实参,会报错
注:没有任何改变,系统自带就有,但不能添加一个有实参的构造,这样系统不会自动生成会报错
2、静态方法实例化
factory是一个中转站,通过改变xml中的获取方式类获取到factory中的new方法,本质还是在获取new中的对象
public static bookdao getOrderDao(){
return new bookdaoimpl();
}
方式二:静态方法实例化
<bean id="bookfactory" class="factory.factory1" factory-method="getOrderDao"></bean>
factory-method用于获取类中的这个方法
3、动态工厂
方法三:动态方法实例化
<bean id="bookfactory" class="factory.factory2"></bean>
<bean id="dao" factory-method="getOrderDao" factory-bean="bookfactory"></bean>
第一步先实例化对象,也就是第二行代码
第二部调用实例化的对象, factory-bean获取第一部的id名
4、factorybean
通过接口来实例化一些方法,减少xml中的操作
public class factory3 implements FactoryBean<bookdao>{
@Override
public boolean isSingleton() {
return true;
}
@Override
public bookdao getObject() throws Exception {
return new bookdaoimpl();
}
@Override
public Class<?> getObjectType() {
return bookdao.class;
}
}
isSingleton()设置是否单例
getObject() 获取返回对象
Type设置继承类型
方法四:factoryBean实例化
<bean id="factoryBean" class="factory.factory3"></bean>
2.3、bean的生命周期
1、直接创建
public void service(){
System.out.println("book dao save.......");
}
public void init(){
System.out.println("init");
}
public void destory(){
System.out.println("destory");
}
需要在xml中加参数
<bean id="bookdao" name="dao book se" class="dao.impl.bookdaoimpl" init-method="init" destroy-method="destory"/>
init-method="init"设置初始化
destroy-method="destory"设置销毁
销毁的执行需要程序中进行close关闭后才能运行
ClassPathXmlApplicationContext cts = new ClassPathXmlApplicationContext("application.xml");
bookdao bookdao = (bookdao)cts.getBean("bookdao");
bookdao.service();
cts.close();
更改了ApplicationContext为ClassPathXmlApplicationContext
增加了cts.close();
2、接口创建实现
public class bookdaoimpl implements dao.bookdao, InitializingBean, DisposableBean {
public void service(){
System.out.println("book dao save.......");
}
@Override
public void destroy() throws Exception {
System.out.println("destory.........");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("init........");
}
}
实现了
InitializingBean, DisposableBean 两个接口
三、注入类型
3.1、setter注入
1、引用类型
就是之前描写的DI依赖注入,引用类型主要用于整个dao方法
private UserDao userDao;
private bookdao bookdao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setBookdao(dao.bookdao bookdao) {
this.bookdao = bookdao;
}
@Override
public void save() {
userDao.save();
bookdao.service();
System.out.println("save....."+mysql+","+it);
}
<bean id="userdaos" class="dao.impl.UserDaoimpl">
<property name="bookdao" ref="bookdao"></property>
<property name="userDao" ref="userdao"></property>
</bean>
ref用于设置这里的名字,name跟类中的名字相同
2、简单类型
private int it;
private String mysql;
public void setIt(int it) {
this.it = it;
}
public void setMysql(String mysql) {
this.mysql = mysql;
}
<bean id="userdao" class="dao.impl.UserDaoimpl">
<property name="mysql" value="diso"></property>
<property name="it" value="1235"></property>
</bean>
value设置里面的值,没有顺序之分
3.2、构造器注入
1、引用类型
public class BookServiceImpl implements BookService{
private BookDao bookDao;
private UserDao userDao;
public BookServiceImpl(BookDao bookDao,UserDao userDao) {
this.bookDao = bookDao;
this.userDao = userDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
userDao.save();
}
}
xml操作:
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<constructor-arg name="bookDao" ref="bookDao"/>
<constructor-arg name="userDao" ref="userDao"/>
</bean>
name和ref代表的意义和之前的相同
2、简单类型
private String databaseName;
private int connectionNum;
public BookDaoImpl(String databaseName, int connectionNum) {
this.databaseName = databaseName;
this.connectionNum = connectionNum;
}
public void save() {
System.out.println("book dao save ..."+databaseName+","+connectionNum);
}
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<constructor-arg name="databaseName" value="mysql"/>
<constructor-arg name="connectionNum" value="666"/>
</bean>
3、命名的其他操作
name的命名可能耦合度过高
1、采取type=“” 类型来进行确定
2、采取index=""位置来进行确定
3.3、自动注入
在xml中进行配置直接进行注入
<bean class="com.itheima.dao.impl.BookDaoImpl"/>
<!--autowire属性:开启自动装配,通常使用按类型装配-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
autowire一般情况使用bytype按类型
当有两个名字的情况进行按名字,名字取决于dao中的private类型
注意:setter类型不能够忘记,不然会报错
3.4、集合
配置
private int[] array;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties properties;
数组
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
List
<property name="list">
<property name="list">
<list>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>chuanzhihui</value>
</list>
</property>
set
<property name="set">
<set>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>boxuegu</value>
</set>
</property>
Map
<property name="set">
<map>
<entry key="country" value="china"/>
<entry key="province" value="henan"/>
<entry key="city" value="kaifeng"/>
</map>
</property>
property
<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">henan</prop>
<prop key="city">kaifeng</prop>
</props>
</property>
四、数据库资源管理
4.1、引入第三方资源
1、引入资源
<denpendency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
2、xml配置
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
4.2、c3p0设置
1、引入资源
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
2、xml配置
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysqal://localhost:3306/spring_db"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
3、aqp展示
//类路径
ApplicationContext cd = new ClassPathXmlApplicationContext("application.xml");
DataSource dataSource = (DataSource) cd.getBean("datasource");
System.out.println(dataSource);
4.3、加载properties文件
1、四个context地方进行修改
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
"
>
</beans>
2、引入properties
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
location="classpath*:.properties" 用于设置路径,两个可以让所有的进行便利
system-properties-mode=“NEVER” 在properties中有些名字和系统的相同,这个可以避免使用系统的
3、使用
<bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
五、容器
5.1、文件类型
类路径
ApplicationContext cd = new ClassPathXmlApplicationContext("application.xml");
文件路径
ApplicationContext sd = new FileSystemXmlApplicationContext("D:\\idea web学习\\demo4\\src\\main\\resources\\application.xml");
多个路径(ctrl+h,查看接口)
ApplicationContext sds = new ClassPathXmlApplicationContext("bean1.xml","bean2.xml");
类路径:直接采用文件名.xml即可,比较方便,类:ClassPathXmlApplicationContext
文件路径:采用的绝对路径,不常用,类:FileSystemXmlApplicationContext
5.2、BeanFactory初始化
顶层接口,了解即可,所有的bean均为延迟加载(不进行get方法不进行构造函数)
六、注解
6.1、xml中bean的替代
1、@Component(“bookdao”)
Component可以总的代表bean类型, 不用到xml中去书写信息
@repository 可以在dao中去使用,给程序员看的,帮助程序员更好的去理解程序
@controller 适用于contronller层
@servicei 适用于service
后面的括号内容为设置的名字
xml内容书写
<context:component-scan base-package="com.example"/>
6.2、xmL资源通过注解在一个类中进行实现
@Configuration
@ComponentScan("example")
public class dst {
}
@Configuration将该类设置为xml内置资源
@ComponentScan(“example”)等同于<context:component-scan base-package=“com.example”/> 相当于设置识别的bean范围
注解开发需要把程序中导入类进行改变
ApplicationContext ct1 = new AnnotationConfigApplicationContext(dst.class);
bookdao bookdao = (bookdao) ct1.getBean("bookdao");
6.3、bean生命周期的设置
@Scope作用 设置是否单例,跟前面的作用一致
可以设置prototype多地址和singleton单地址(默认为单地址)
@postconstruct 设置初始化,需要先导入Java.annotion
@predestroy 设置销毁,程序多地址时没有,多地址默认不使用生命周期
6.4、依赖注入
1、引用类型注入
@Autowired 自动注入,不用再set设置,构造函数可以直接实现
@Service("bookservice")
public class bookserviceimpl implements bookservice {
@Autowired
@Qualifier("bookdao")
//删除业务层中使用new的方式创建的dao对象
private bookdao bookDao;
public void service(){
System.out.println("book service save......");
bookDao.service();
}
}
@Qualifier与 @Autowired是相互匹配的,可以设置注入的对象,想当于下面的private
2、简单类型注入
@Value("123")
private String op;
public void service(){
System.out.println("book dao save......."+op);
}
@Value(“123”) 可以设置op的值为123
简单类型通过内置资源随时进行改变值
@Configuration
@ComponentScan("example")
@PropertySource("jdbc.properties")
public class dst {
}
xml类中进行设置
@PropertySource(“jdbc.properties”)与内置资源进行联系
properties设置
name = 123;
设置位置
@Value("${name}")
private String op;
public void service(){
System.out.println("book dao save......."+op);
}
通过value进行读取
6.5、第三方bean配置导入
@Bean表示当前方法的返回值设置为Bean
jdbc设置
//Bean表示当前方法的返回值设置为Bean
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysqal://localhost:3306/spring.db");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
}
程序中的设置
//第三方的引入
ApplicationContext op = new AnnotationConfigApplicationContext(dst.class);
DataSource dataSource = (DataSource) op.getBean("dataSource");
System.out.println(dataSource);
dst中设置导入
@Configuration
@ComponentScan("example")
@PropertySource("jdbc.properties")
@Import(jdbc.class)
public class dst {
}
@Import进行导入
第三方类型进行注入操作
1、 引用类型
直接进行导入既可以使用了
2、简单类型
@Value("com.mysql.jdbc.Driver")
private String tname;
@Value("jdbc:mysqal://localhost:3306/spring.db")
private String tUrl;
@Value("root")
private String root;
@Value("123456")
private String password;
设置一个使用一个
6.6、对比
七、spring和Mybatis的结合
项目结构
7.1、dao设计
@Component("userMapper")
public interface UserMapper {
user getUserId(int id);
}
<resultMap id="users" type="com.pojo.user">
<result column="pwd" property="password"></result>
</resultMap>
<select id="getUserId" resultMap="users" parameterType="int" >
select * from mybatis.user where id=${id};
</select>
7.2、pojo设计
@Date
@All
@No
public class user {
private int id;
private String name;
private String password;
}
7.3、service设计
@Service
public class userService implements userserviceimpl {
@Autowired
private UserMapper userMapper ;
@Override
public user getUserIds(int id) {
return userMapper.getUserId(id);
}
}
public interface userserviceimpl {
user getUserIds(int id);
}
7.4、zhujie设计
jdbc
public class jdbc {
@Value("${jdbc.name}")
private String name;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.root}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(name);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
Mybatis
public class Mybatis {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sq = new SqlSessionFactoryBean();
sq.setDataSource(dataSource);
return sq;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer ms = new MapperScannerConfigurer();
ms.setBasePackage("com/dao");
return ms;
}
}
xml
@Configuration
@ComponentScan("com")
@PropertySource("cp.properties")
@Import({ Mybatis.class,jdbc.class})
public class xml {
}
7.5、程序使用
public class app {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(xml.class);
userService bean = context.getBean(userService.class);
// UserMapper bean = context.getBean(UserMapper.class);
user userId = bean.getUserIds(2);
System.out.println(userId);
}
}
7.6、资源设置
jdbc.name = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis?useSSL=true&characterEncoding=UTF-8&useUnicode=true&serverTimezone=GMT
jdbc.root = root
jdbc.password = 123456
7.7、pom设置
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.1.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
理解:Mybatis为主体框架,首先是dao的设计,确定要使用的方法,可以在dao中的接口用注解的方法进行实现,也可以用xml进行代码操作,然后设计数据库的类型在pojo中完成,在service中引入dao(通过依赖注入),最重要的在zhujie中进行整体框架的构建,xml实现内置资源,jdbc完成数据库操作,mybatis完成Mybatis的操作,再整体导入xml中,整个程序只要调用xml和需要的service类就能进行
8、spring整合junit(测试类进行)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = xml.class)
public class userTest extends TestCase {
@Autowired
private UserMapper userMapper ;
@Test
public void testID(){
user userId = userMapper.getUserId(2);
System.out.println(userId);
}
}
前两个类是为了要自动装配的完成
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = xml.class)
八、AOP(面向切面程序)
8.1、基础知识
连接点:可以是程序执行时的任意位置
在springboot中可以特指方法的执行
切入点:需要进行匹配的方法
通知:需要加入的信息写在里面
切面:描述通知与切入点的对应关系
8.2、基础程序的创建
1、myadvice
@Component
@Aspect
public class myadvice {
@Pointcut("execution(void com.service.AopService.updates())")
private void pd(){}
@Before("pd()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
@Component 设置为bean方法已进行实现
@Aspect 设置整个 类型为切面
@Pointcut(“execution(void com.service.AopService.updates())”) 设置切面的位置
void表示类型 后面到具体位置的方法
private void pd(){} 别名的设置,相当于将所在位置的方法设置为这个别名
@Before(“pd()”) 设置执行的顺序
public void method(){
System.out.println(System.currentTimeMillis());
}
设置要实现的方法
2、xml
@Configuration
@ComponentScan("com")
@EnableAspectJAutoProxy()
public class xml {
}
@EnableAspectJAutoProxy() 开启aspects的自动代理
8.3、工作流程
代理表现
System.out.println(bean.getClass());
bean.getClass获取的内容即可查看是否为代理对象
8.4、AOP表达式的格式
1、切入点的两种表达方式
类中:
@Pointcut("execution(void com.service.AopService.updates())")
接口中:
@Pointcut("execution(void com.service.impl.AOpServiceimpl.updates())")
2、标准格式
注意:方法返回类型千万不能忘记
3、 符号代替描述
1、*
可以代替一整个类或方法,也可以代替后缀前缀
2、…
…匹配的范围更大,可以将多个类路径一起描述,也可以说明是否有值,不用像*必须确定个数
3、书写技巧
描述返回类型为public时可以省略不写
返回类型为增删改时用精准匹配,为查询时用*匹配
包名中尽量不使用…,匹配效率太低
接口名采用 * 匹配,如*service
8.5、AOP的通知类型
1、前置通知
@Before()
在事务的前面进行实现
2、后置通知
@After
在事务的后面进行
3、环绕通知(重点)
@Around("pd()")
public Object method(ProceedingJoinPoint pro) throws Throwable {
System.out.println(System.currentTimeMillis());
Object proceed = pro.proceed();
System.out.println(System.currentTimeMillis());
return proceed;
}
可以设置事务在语句中进行
ProceedingJoinPoint pro代表设置的对象
Object用于设置返回值,记得类型的改变上面的void的类型也要改变
4、返回值后通知
@AfterReturning
用于有返回值后再给通知,保异常不给
5、报错后通知
@AfterThrowing
用于有报错后再进行通知,没有报错则不进行
8.6、AOP中获取参数和返回参数
1、AOP中获取类型和名字
@Pointcut("execution(* com.service.impl.userService.*(..))")
private void pd(){}
@Around("pd()")
public void method(ProceedingJoinPoint pro) throws Throwable {
long t1 = System.currentTimeMillis();
Signature signature = pro.getSignature();
Class declaringType = signature.getDeclaringTypeName().getClass();
String name = signature.getName();
for(int i=0;i<10000;i++)
pro.proceed();
long t2 = System.currentTimeMillis();
System.out.println("该"+declaringType+":"+name+"---------->"+"执行"+(t2-t1)+"ms");
}
Signature signature = pro.getSignature();为引用该类型
Class declaringType = signature.getDeclaringTypeName().getClass(); 获取类型名
String name = signature.getName();获取名字
2、获取参数值
@After("pd()")
public void method(JoinPoint jp){
Object[] args = jp.getArgs();
System.out.println("输入的值为:"+ Arrays.toString(args));
}
Arrays.toString(args)需要加这个进行转换
通过getArgs进行完成
3、将返回值进行改变
@Around("pd()")
public Object method(ProceedingJoinPoint pro) throws Throwable {
Object[] args = pro.getArgs();
System.out.println(Arrays.toString(args));
args[0] = 10;
Object proceeds = pro.proceed(args);
return proceeds;
}
重新设置过后通过proceed重新传回去
4、获取返回值数据
@AfterReturning(value = "pd()",returning = "i")
public void method(int i){
System.out.println("js:"+i);
}
有返回值后输出,可以自己设置类型
@AfterThrowing(value = "pd()",throwing = "jps")
public void method(Throwable jps){
System.out.println("异常:"+jps);
}
有异常的时候输出,可以在around中进行
九、事务管理
原理:在数据操作时同成功,同失败
作用:比如银行转账时,需要一个账户扣钱,一个加钱,如果出现异常的情况这个过程就可能出错,所以可以用事务进行管理
9.1、实现条件:
1、在接口或类中添加事务
@Transactional
public void transfor(String out,String in,int money);
2、在 配置文件中指明位置
@Configuration
@ComponentScan("com")
@PropertySource("cp.properties")
@Import({ Mybatis.class,jdbc.class})
@EnableTransactionManagement
3、在数据库中进行操作
public PlatformTransactionManager platformTransactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
9.2、事务的方法使用
@Transactional(readOnly = true)
可以直接进行设置
rollbackFor的使用主要是因为有两个异常不会进行数据回滚,需要进行设置
9.3、事务的传播
事务是可以通过设置来确定是否传播的
@Transactional(propagation = Propagation.REQUIRES_NEW)
这个就是创建一个新的事物管理员,跟之前的事物进行分开
SUPPORTS是有事物管理员时就加入,没有就不创建
NOT_SUPPORTS是无论如何都不创建事务
MANDATORY是有事务就加入,没有就报错
NEVER是没有事务
这个是我之前在学习过程中所写的笔记,可能其中的内容会有一些缺漏之处,欢迎大家在评论区里面进行指出,另外这篇博文只是将spring部分进行粗略的写出,详细部分可以去看一下我的Spring模块下的其他内容,后续的SpringMvc和SpringBoot会在后面的文章中进行发表
参考资料