Spring AOP概念与应用学习
介绍
本篇文章将通过实现事务控制
示例来学习AOP
思想。示例代码仓库为:Spring AOP概念与应用学习(gitee.com)。
参考资料
文中示例代码使用的是B站UP主程序员的梦姐姐呀的视频:10分钟后,再也不用死记硬背SpringAOP八股了_哔哩哔哩_bilibili中展示的代码,我加上了自己的理解注解,以此来帮助其他读者更好的理解每一处代码的作用,如果侵权,可联系本人删除。
相关概念
AOP(面向切面编程)
相关概念:
1.切面: 拦截处理类,示例中指的是:TransactionManagerHandler
;
2.切入点: 拦截规则,分别有 前置:before
;后置:after-returning
;异常:after-throwing
;最终:after
;
3.连接点: 具体背拦截到的方法,示例中指的是:service.impl.UserServiceImpl.insert()
;
4.通知: 在不同的场景下拦截的功能,即在不同拦截规则中具体实现的逻辑;
5.织入: 由spring完成,切面类包裹住对象,创建出代理对象。
两种形式
XML文件配置实现
XML文件配置实现AOP
示例项目文件结构如下图所示:
其中lib
库中使用到的是各类jar
包,src
目录下则是示例代码。
如果项目使用xml
文件进行配置比较多,则在原有的项目逻辑上通过新增xml
文件来编写AOP
配置则可以实现通过AOP
的方式来实现事务控制
。具体的xml
文件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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="UserService" class="service.impl.UserServiceImpl"></bean>
<bean id="TransactionManager" class="service.TransactionManagerHandler"/>
<aop:config>
<!--
AOP相关概念:
1.切面:拦截处理类,示例中指的是:TransactionManagerHandler
2.切入点:拦截规则,分别有 前置:before;后置:after-returning;异常:after-throwing;最终:after
3.连接点:具体背拦截到的方法,示例中指的是:service.impl.UserServiceImpl.insert()
4.通知:在不同的场景下拦截的功能,即在不同拦截规则中具体实现的逻辑
5.织入:由spring完成,切面类包裹住对象,创建出代理对象
-->
<!--配置切面-->
<aop:aspect ref="TransactionManager">
<!--配置切入点,pt是pointcut的别称-->
<aop:pointcut id="pt" expression="execution(public void service.impl.UserServiceImpl.insert())"/>
<!--在切入点的各个拦截规则中配置通知-start-->
<!--表示在pt所指代的方法执行之前执行method中指定的方法,这里执行begin方法-->
<aop:before method="begin" pointcut-ref="pt"/>
<!--表示在pt所指代的方法执行完成正常返回之后执行method中指定的方法,这里执行commit方法-->
<aop:after-returning method="commit" pointcut-ref="pt"/>
<!--表示在pt所指代的方法执行发生异常时执行method中指定的方法,这里执行rollback方法-->
<aop:after-throwing method="rollback" pointcut-ref="pt"/>
<!--表示在pt所指代的方法执行最后执行method中指定的方法,这里执行closeSession方法-->
<aop:after method="closeSession" pointcut-ref="pt"/>
<!--在切入点的各个拦截规则中配置通知-end-->
</aop:aspect>
</aop:config>
</beans>
事务控制
具体实现逻辑类TransactionManagerHandler.class
代码如下:
package service;
public class TransactionManagerHandler {
public void begin(){
System.out.println("开启事务!");
}
public void commit(){
System.out.println("提交事务!");
}
public void rollback(){
System.out.println("回滚事务!");
}
public void closeSession(){
System.out.println("关闭链接!");
}
}
通过执行AopTest.class
中的测试代码即可得到效果,效果如下:
由此可见事务控制
逻辑按照实现配置好的顺序执行完成,通过在逻辑代码中抛出测试异常来测试事务回滚逻辑是否实现,修改后的代码如下:
package service.impl;
import service.UserService;
public class UserServiceImpl implements UserService {
@Override
public void insert() {
System.out.println("执行插入逻辑!");
throw new RuntimeException("测试");
}
}
重新运行测试方法得到如下结果:
由此可见异常回滚逻辑也可正常执行。
注解配置实现
注解配置实现AOP
示例项目文件结构如下图所示:
其中lib
库中使用到的是各类jar
包,src
目录下则是示例代码。
注解配置实现与xml
文件配置实现得最大不同点在于移除了繁琐的xml
配置,通过SpringConfig.class
配置类来完成AOP
的基础配置,配置类SpringConfig.class
内容如下所示:
package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
//声明这个是配置类
@Configuration
//配置要扫描的包,这里配置扫描service包,如果不配置,由于没有xml文件进行配置,则会造成pointcut无法识别到bean:UserService
@ComponentScan("service")
//启用aop代理注解
@EnableAspectJAutoProxy
public class SpringConfig {
}
切面控制类中需要添加AOP
相关注解来实现具体的配置,修改后的切面控制类TransactionManagerHandler.class
文件内容如下:
package service;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//将类交由Spring容器进行管理
@Component
//表明该类是切面控制类
@Aspect
public class TransactionManagerHandler {
@Pointcut("execution(public void service.impl.UserServiceImpl.insert())")
public void pointcut(){}
@Before("pointcut()")
public void begin() {
System.out.println("开启事务!");
}
@AfterReturning("pointcut()")
public void commit() {
System.out.println("提交事务!");
}
@AfterThrowing("pointcut()")
public void rollback() {
System.out.println("回滚事务!");
}
@After("pointcut()")
public void closeSession() {
System.out.println("关闭链接!");
}
}
业务逻辑代码实现类UserServiceImpl.class
中需要添加@Service
注解,修改后的代码如下:
package service.impl;
import org.springframework.stereotype.Service;
import service.UserService;
@Service
public class UserServiceImpl implements UserService {
@Override
public void insert() {
System.out.println("执行插入逻辑!");
}
}
测试类中由于不再使用xml
文件进行配置,因此需要对测试类AopTest.class
代码进行修改,修改后的代码如下:
package test;
import config.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import service.UserService;
public class AopTest {
@Test
public void testInsert() {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean(UserService.class);
userService.insert();
}
}
测试类执行结果如下:
由此可见事务控制
逻辑按照实现配置好的顺序执行完成,测试异常情况事务回滚逻辑执行结果如下:
由此可见异常回滚逻辑也可正常执行。
结束语
通过简单的两个小的事务控制示例项目可以充分理解AOP
思想的应用,文中如果有错误的地方欢迎各位读者指出,同时也感谢B站UP主程序员的梦姐姐呀的知识分享。