Spring(AOP)
AOP 介绍
- AOP(Aspect Oriented Programming) 面向切面编程。
- IOC/DI:AOP的核心是IOC必须在容器里面管理。
- 采用动态代理对类对象进行增强。
为什么需要AOP
需要原因
在不改变代码情况下对方法进行增强
-
在类的方法的层面进行增强 ,首先思考的是在哪里进行对bean的增强
- 在类字节码上增强 带有入侵性
- 在对象上动态代理增强 OK
- 对bean的方法进行增强,产生了对那些方法进行增强,怎么增强
-
Advice (通知) 提供前后环绕增强的接口 由用户实现
Advice (通知 增强的功能)
接口定义:
前置增强
后置增强
环绕增强/异常处理 (异常也是环绕)
分成三个接口 -
Join points 切入点(可以做增强的方法)
-
Pointcut (切入点 实际需要做切入的地方 用户指定的)
-
Aspect (切面 多个切点组成的 可以以包的维度进行切入)
Aspect (选择多个点进行增强 AspectJ )
https://docs.spring.io/spring/docs/5.1.1.RELEASE/spring-framework-reference/core.html#aop-pointcuts
https://www.cnblogs.com/loongss/p/5774859.html -
Advisor (是把 Advice和我们 Pointcut(Aspect) 关联起来)
advisor 是关联我的advice 和 Aspect 所以主要注册我们advisor -
Weaving(织入)
-
Weaving(织入 不改变源代码进行增强) 怎么把我的advisor的东西注册上去 (通过动态代理去织入进去)
将用户增强的功能增加到指定的方法上。
首先的思路是在工厂方法中创建对象完成之后用cglib 去生成代理对象把代理对象放进去
工厂方法庞大 不灵活 -
分析:bean 产生的过程
在初始化完成后前后通过观察者模式来处理
AdvisorAutoProxyCreator 包含了 advisor (AspectJPointcutAdvisor 这里面有一个beanName 就是我们的advice 的beanName : advice用户提供的 既然是用户提供的 必然要在我们的工厂里面管理)
AdvisorAutoProxyCreator 是提供了一个织入的方式 (会在我bean创建前后得到通知 去做处理)
BeanFactoryAware 里面为啥要 setBeanFactory 方法是因为你的advisor是包含的beanName需要通过工厂获取
里面提供了CglibDynamicAopProxy 和 JdkDynamicAopProxy
public static Object applyAdvices(Object target, Method method, Object[] args, List<Advisor> matchAdvisors,
Object proxy, BeanFactory beanFactory) throws Throwable {
// 这里要做什么?
// 1、获取要对当前方法进行增强的advice
List<Object> advices = AopProxyUtils.getShouldApplyAdvices(target.getClass(), method, matchAdvisors,
beanFactory);
// 2、如有增强的advice,责任链式增强执行
if (CollectionUtils.isEmpty(advices)) {
return method.invoke(target, args);
} else {
// 责任链式执行增强
AopAdviceChainInvocation chain = new AopAdviceChainInvocation(proxy, target, method, args, advices);
return chain.invoke();
}
}
对于匹配了多个增强器(advisor)采取责任链的模式来进行处理
注意:
在用户自定义前置后置增强的器中是不需要做增强的,否则进入死循环