什么是AOP?
相比于面向切面编程,我更喜欢把AOP叫做方法增强,我用一幅图来解释下。
一句话概述就是在不影响原方法的情况下对其进行代码方法的补充、增强。
Spring是如何实现AOP的
说到Spring的AOP就要讲到Java的动态代理设计模式
什么是动态代理?
用个简单的例子来说明:
现在有A、B、C三个对象
A想直接访问C,C不允许A直接访问,而A委托B做它的代理类,所有想访问C的对象(例如A),都必须通过B来访问C;
结论:给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问
而Spring就是基于动态代理模式实现的AOP,底层使用JDK动态代理和Cglib的的动态代理
关于JDK的动态代理和Cglib的动态代理此处就不做具体说明。
AOP常应用在哪些地方?
其实我们工作中常见的AOP的实现大部分是配合自定义注解来使用
1、Spring的事务,@Transactional注解在方法之上开启数据库的事务,方法执行完做一个事务的提交,出现异常则回滚。
2、权限的验证,特别是在ERP系统中,需要判断访问用户是否有此接口的权限来做一个控制,也是通过注解和AOP来实现
3、用户操作记录/log日志,作者之前就写过一个业务,就是要记录每个用户每天访问了哪些接口,做了哪些事情。也是利用AOP实现
4、等等、、、
AOP中的相关概念(术语,面试会问)
1.切点:在方法的哪里做增强配合通知使用
2.通知:切面做什么,何时使用,配合切点就知道在哪里,什么时候,做什么,Spring定义了5中通知:
前置通知(Before),后置通知(After),环绕通知(Around),最终通知(finally),异常通知(Throwing )
前置通知就是在原方法执行前做通知增强
后置通知就是原方法执行完做通知增强
环绕就是原方法执行前后都做通知增强
最终就是不管如何都做一个通知增强
异常原方法发生异常的情况下做通知增强
3. Aspect(切面): 切面是通知和切点的结合,通知和切点共同定义了切面的全部内容。因为通知定义的是切面的"要做什么"和"在何时做"
而切点定义的是切面的"在何地做"。将两者结合在一起,就可以完美的
4.连接点:增强的方法和原方法连接的地方,一般Spring提供了JoinPoint对象来存储原方法的信息
案例
使用自定义注解对已有方法进行增强
1、使用Springboot进行测试,引入AOP的maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、自定义注解
/**
* @Author: whr
* @TODO: aop测试
* @Date: create in 2021/3/16 19:56
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopTest {
}
3、注解实现
/**
* @Author: whr
* @TODO:
* @Date: create in 2021/3/16 19:57
*/
@Aspect
@Component
public class AopTestAspect {
@Pointcut("@annotation(AopTest)")
public void pointCut() {
}
/**
* 前置增强
* @param joinPoint
* @param aopTest
*/
@Before("pointCut()&&@annotation(aopTest)")
public void before(ProceedingJoinPoint joinPoint, AopTest aopTest) {
System.out.println("参数打印:" + JSONObject.toJSONString(joinPoint.getArgs()));
System.out.println("方法执行前进行增强!");
}
/**
* 后置增强
* @param joinPoint
* @param aopTest
*/
@After("pointCut()&&@annotation(aopTest)")
public void after(ProceedingJoinPoint joinPoint, AopTest aopTest){
System.out.println("方法执行完毕进行增强!");
}
}
4、编写接口进行测试
/**
* @Author: whr
* @TODO: 接口测试
* @Date: create in 2021/3/16 20:02
*/
@RestController
@AllArgsConstructor
public class TestController {
@GetMapping("/aop")
@AopTest
public void aopTest(@RequestParam String name){
System.out.println("原方法执行中!");
}
}
请求接口:
http://localhost:4006/aop?name=张三
端口自己定义
总结(借助网友评论):
在AOP中切面就是与业务逻辑独立,但又垂直存在于业务逻辑的代码结构中的通用功能组合;切面与业务逻辑相交的点就是切点;连接点就是把业务逻辑离散化后的关键节点;切点属于连接点,是连接点的子集;Advice(增强)就是切面在切点上要执行的功能增加的具体操作;在切点上可以把要完成增强操作的目标对象(Target)连接到切面里,这个连接的方式就叫织入