【Spring】AOP思想
【摘要】 这篇文章主要介绍了AOP面向切面编程的概念和作用,以及切入点、通知、切面的内容,后面介绍通知的类别(5类),最后介绍在通知中如何获取并处理数据。
这篇文章主要介绍spring中AOP相关的知识。
AOP是面向切面编程(Aspect Oriented Programming)的简写,就像我们之前学习过面向对象编程(OOP,Object Oriented Programming),同样是一种程序设计思想,其作用是,在无需修改代码的前提下,对业务增加统一的功能,比如日志记录,权限控制,事务管理等,使得代码更加解耦,提高开发效率。
连接点:在spring中连接点可以指某个类中所有的方法
切入点:类中需要做功能增强的方法
通知:包含功能增强的代码的方法
通知类:通知所在的类
切面:建立切入点与通知之间的联系
1.准备工作(事先准备好dao和实现类)
2.导入AOP相关依赖
<!-- AOP相关依赖-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!-- spring框架(包含了spring-aop)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
3.使用@Component和@Aspect编写通知类(切面类)
4.使用@PointCut在方法壳上定义切入点(实际是方法)
5.使用@Before/@After注解定义切面
6.使用@EnableAspectJAutoProxy注解告知SpringConfig类开启AOP支持
7.运行主类查看结果
由此可见,在insert()方法执行前执行了通知,AOP执行成功。
1.spring容器启动
2.读取切面中的切入点方法
3.初始化bean,并判断bean中的方法是否匹配到切入点
(1)匹配成功
运行结果:
(2)匹配失败
运行结果:
4.总结:
举例:
(1)使用*
(2)使用…
(3)使用+
首先准备好了dao-BookDao和实现类BookDaoImpl,以及通知类Advice
public interface BookDao {
void insert();
int select();
}
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void insert() {
System.out.println("book dao insert ...");
// int i = 1/0;
}
@Override
public int select() {
System.out.println("book dao select ...");
return 68;
}
}
为两个方法定义好了切入点
@Pointcut("execution(void demo7.dao.BookDao.insert())")
private void fn1() {
}
@Pointcut("execution(int demo7.dao.BookDao.select())")
private void fn2() {
}
运行结果:
和前置通知类似,只是在原始方法执行后执行通知,下面直接来看运行结果
运行结果:
运行结果:
注意事项:
注意事项 |
---|
1.环绕通知必须有ProceedingJoinPoint类型的方法形参,用于执行原始方法 |
2.如果没有这个形参,原始方法不执行 |
3.由于未知原始方法是否会抛异常,因此这个切面方法必须抛异常 |
4.如果原始方法有返回值,切面方法的返回值必须是Object类型 |
5.如果原始方法是void类型,切面方法也可以是Object类型 |
运行结果:
@After和@AfterReturning对比
@After | @AfterReturning |
---|---|
原始方法发生异常时仍然通知 | 原始方法正常return才通知 |
运行结果:
1.准备工作
准备好了实体类,mapper接口和service和和实现类,以及三个配置文件和jdbc.properties文件,下面是通知类(使用Signature类获取执行的方法有关信息)
@Component
@Aspect
public class Advice {
// 为两个方法设置切入点
@Pointcut("execution(* demo8.service.*Service.select*(..))")
private void selectPt() {
}
// 设置切面
@Around("selectPt()")
public Object method(ProceedingJoinPoint point) throws Throwable {
Signature signature = point.getSignature();
String methodName = signature.getName(); // 获取方法名
String typeName = signature.getDeclaringTypeName(); // 获取方法类型
long startTime = System.currentTimeMillis(); // 获取执行前的系统时间
Object o = null;
for (int i = 0; i < 1000; i++) {
o = point.proceed();
}
long endTime = System.currentTimeMillis(); // 获取执行后的系统时间
System.out.println("执行"+typeName+"类型的"+methodName+"方法花费时间:" + (endTime - startTime) + "ms");
return o;
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
@Autowired
private UserService service;
@Test
public void testSelectAll() {
List<User> users = service.selectAll();
System.out.println(users);
System.out.println(users.size());
// 获取方法有关信息
}
@Test
public void testSelectById() {
User user = service.selectById(2);
System.out.println(user);
}
}
测试结果:
五种通知都可以获取方法参数,一般使用JoinPoint类型形参的getArgs()方法,在环绕通知中(@Around)使用ProceedJoinPoint类型的getArgs()方法。
举例:
(1)JoinPoint对象
@Before("fn1()")
public void before(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs(); // 1.前置通知获取切入点方法参数
System.out.println(Arrays.toString(args));
System.out.println("before ...");
}
业务层接口和实现类:
主类和运行结果:
(2)ProceedJoinPoint对象
只有返回后通知@AfterReturning和环绕通知@Around可以获取
(1)环绕通知
(2)返回后通知
使用Object类型的方法形参,并在注解上加returning = 形参名称
只有抛出异常后通知@AfterThrowing和环绕通知@Around可以获取
(1)环绕通知
首先在serviceImpl抛出一个异常
(2)抛出异常后通知
使用Throwable 类型的形参,并在注解上加上throwing = 形参名称
这篇文章主要介绍了AOP面向切面编程的概念和作用,以及切入点、通知、切面的内容,后面介绍通知的类别(5类),最后介绍在通知中如何获取并处理数据。
AOP是spring的核心思想之一,前面学习了IOC(控制反转),至此开始越来越了解spring的工作机制。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)