Spring AOP 源码学习笔记
极客学长 2022-11-16 0
Spring 源码系列
刘慈欣 -《三体》
弱小和无知不是生存的障碍,傲慢才是。
# 01 - Spring ProxyFactory
ProxyFactory 是 Spring 实现的一个代理工厂类,它也是 Spring AOP 和 Spring 事务实现的底层技术支撑。平时我们在业务代码中也可以使用它,因为用它来创建动态代理对象真实太方便了!!!只需简单的三步:
- 创建 ProxyFactory 对象
- 设置被代理的 Target
- 获取代理对象
最关键的是,ProxyFactory 会自动判断你要使用 JDK 还是 CGLIB 来创建代理对象:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果ProxyFactory的isOptimize为true,Spring认为 cglib比jdk动态代理要快
// 或者isProxyTargetClass为true,
// 或者被代理对象没有实现接口,
// 或者只实现了SpringProxy这个接口
// 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理
// 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口
// 是不是在GraalVM虚拟机上运行
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
下面来看一个 ProxyFactory 的使用 Demo:
// 创建被代理对象
OrderService orderService = new OrderService();
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
// 设置被代理对象
proxyFactory.setTarget(orderService);
// 添加一个 Advice, 实现切面方法
proxyFactory.addAdvice(new MethodInterceptor() {
@Nullable
@Override
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable
{
System.out.println("Around 前");
Object proceed = invocation.proceed();
System.out.println("Around 后");
return proceed;
}
});
// 获取代理对象
OrderService proxy = (OrderService)proxyFactory.getProxy();
// 代理对象执行方法
proxy.test();
有木有觉得如丝般顺滑 O(∩_∩)O 哈哈~
# 02- AOP 的启动流程
- 通过
@EnableAspectJAutoProxy
注解引入 AspectJAutoProxyRegistrar 类, 从而注册一个 AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor - 具体 AOP 的入口在 AnnotationWareAspectJAutoProxyCreator 的父类 AbstractAutoProxyCreator 的
postProcessAfterInitialization()
方法:public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); // 包装成 AOP 代理对象 } } return bean; }
- 判断当前 bean 是否需要进行 AOP(是否存在匹配的 Advice),如果不需要则直接返回原对象,否则生成一个代理对象返回。
# 03 - 匹配 Advice 的具体逻辑
如何判断当前 Bean 是否存在匹配的 Advice 呢?具体实现过程如下:
先找到当前 Bean 容器中所有的 Advisor 类型的 Bean 对象,得到 advisors 列表
再从所有的切面中解析得到 Advisor(最终会封装成 InstantiationModelAwarePointcutAdvisorImpl 对象),将其加入 advisors 了列表中。
protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 先找到所有Advisor类型的Bean对象 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. // 再从所有切面中解析得到Advisor对象 if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; } // 具体封装 Advisor 逻辑在 ReflectiveAspectJAdvisorFactory::getAdvisor() 方法 public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); // 拿到当前方法所对应的Pointcut对象,但是注意:如果当前方法上是这么写的@After("pointcut()"),那么此时得到的Pointcut并没有去解析pointcut()得到对应的表达式 AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } // expressionPointcut是pointcut // candidateAdviceMethod承载了advice return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
根据当前 beanClass 类型对所有候选的 Advisor 进行筛选,筛选之后对 Advisor 进行排序。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 找到所有的Advisor List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 进行筛选 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); // 对Advisor进行排序,按Ordered接口、@Order注解进行排序 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
# 04 - 切面的筛选逻辑
具体实现在 AopUtils::canApply() 方法中
- 先判断类,如果类型不匹配则直接返回 false
if (!pc.getClassFilter().matches(targetClass)) { return false; }
- 判断方法匹配器 MethodMatcher, 遍历所有的方法,如果有一个方法匹配就返回 true
for (Method method : methods) { if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : // 判断方法是否匹配 methodMatcher.matches(method, targetClass)) { return true; } }
# 05 - 创建代理对象的过程
- 创建一个 ProxyFactory 对象
- 添加 Advisors(
proxyFactory.addAdvisors(advisors)
), 这里需要把匹配到的 Advice 包装成 Advisor 对象:- 如果本身就是 Advisor 对象,则直接强制转成 Advisor 对象并返回
- 如果是 MethodInterceptor 对象,则包装成 DefaultPointcutAdvisor 对象。
- 如果实现了具体的 AdvisorAdapter 接口(AfterReturningAdviceAdapter/MethodBeforeAdviceAdapter/ThrowsAdviceAdapter),将其包装成 DefaultPointcutAdvisor 对象
- 设置被代理对象(
proxyFactory.setTargetSource(targetSource)
);
# 06 - 代理对象的执行过程(核心)
- 使用 ProxyFactory 创建代理对象之前,先要往 ProxyFactory 中添加 Advisor 。
- 代理对象在执行某个方法时,先判断一下如果是
hashCode()
或者equals()
方法则不走代理,直接调用被代理对象的方法。 - 如果当前执行的方法需要走代理,则会先把 ProxyFactory 中所有的 Advisor 拿出来个当前的执行的方法进行匹配。
- 如果匹配的结果为空,则直接调用 target 对应的方法,将匹配成功的 Advisor 都适配成 MethodInterceptor 对象(AfterReturningAdviceAdapter/MethodBeforeAdviceAdapter/ThrowsAdviceAdapter),并按照顺序放入一个列表中,形成一个调用链(chain)。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- 将代理对象(proxy),被代理对象(target), 当前调用方法(method),代理类和调用链(chain) 封装成一个
MethodInvocation
对象。MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed();
- 调用
invocation.proceed()
方法,开始执行各个 MethodInterceptor 以及被代理对象的对应方法,具体执行逻辑在ReflectiveMethodInvocation::proceed()
方法中。 - 通过递归的方式,一层一层调用对应 Advisor 中的 MethodInterceptor 中的
Invoke()
方法,需要留意的是,这里会对 Advisor 再进行一次筛选:InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); // 动态匹配,根据方法参数匹配 if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. // 不匹配则执行下一个MethodInterceptor return proceed(); }
- 直到执行完最后一个 MethodInterceptor 了,就会调用
invokeJoinpoint()
方法,从而执行被代理对象的当前方法// 当调用完了最后一个interceptor后就会执行被代理方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
如果您觉得本文对您有用,可以请作者喝杯咖啡。 如需商务合作请加微信(点击右边链接扫码): RockYang
版权申明 : 本站博文如非注明转载则均属作者原创文章,引用或转载请注明出处,如要商用请联系作者,谢谢。