二刷AOP源码(下)

简介: 二刷AOP源码(下)
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
        【1】是否有适合当前Bean的建议者。
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
      【2】创建代理对象
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

getAdvicesAndAdvisorsForBean:

  • 先执行上文提到的寻找建议者的逻辑,找到当前上下文存在的建议者
  • 判断建议者是否给当前Bean提了建议(引介增强会使用类匹配,切点增强会使用切点的MethodMatcher进行匹配),提了建议就创建代理。


2.2.4.代理的创建

有了建议者,有了目标对象,创建代理也就顺理成章。但创建所涉及的功能组件却没有那么简单。


(1)JdkDynamicAopProxy与CglibAopProxy

  • JdkDynamicAopProxy:是对JDK动态创建代理的封装,JdkDynamicAopProxy本身就是一个InvocationHandler,并提供getProxy方法,通过反射Proxy创建代理。
  • CglibAopProxy:对CGLB动态代理创建的封装。getProxy通过Enhancer+DynamicAdvisedInterceptor创建代理对象

这两种增强都会有一个AdvisedSupport属性保存建议者。

private final AdvisedSupport advised;

这两个是底层封装,Spring创建代理并没有直接调用他们,而是封装了三个更高层次的组件


(2)AspectJProxyFactory与ProxyFactoryBean与ProxyFactory

这三个组件都是AdvisedSupport的子类。

这三个组件都可以用作创建代理对象,他们上没有本质的区别,都是ProxyCreatorSupport的子类。创建代理对象的逻辑调用也在ProxyCreatorSupport中。


多个建议者告诉ProxyCreatorSupport ,ProxyCreatorSupport会调用策略工厂AopProxyFactory选择JdkDynamicAopProxy或者CglibAopProxy创建代理对象。


protected Object createProxy(
            Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
    【1】ProxyFactory组件
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);
      【2】设置建议者
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
      【3】创建代理对象
        return proxyFactory.getProxy(getProxyClassLoader());
    }

此时,我们定义的建议者正式与JDK或者CGLB挂上了钩

可以看出,简简单单的JDK,CGLB代理。Spring 融入此功能时做了多么复杂的设计。


2.2.5.代理的执行

以JDK动态代理为例,执行invoke方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
[1]
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
[2]
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
[3]
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
  • (1)从AdvisedSupport获建议者链,此过程通过AdvisorChainFactory组件完成,将适用于当前目标对象的建议者取出来,创建一个执行建议链。
  • (2)根据建议链等信息,创建一个MethodInvocation执行器
  • (3)执行得到结果

代理类其实也是实现了Advied接口,但是内存生成的那个类,并不会展示Advied接口,但是通过instance of 查看可以查看。


3.总结


AOP之所以复杂,就在于Spring在上层建筑上所做的东西比较多。其本质就是JDK动态代理(Proxy+InvocationHandler)与CGLB(Enhancer + MethodInterceptor(CallBack))

搞清楚SpringAOP组件的角色,以及与底层基础的连接点。理解AOP就不难了。

万层高楼平地起,抓住根 与 主干,就能窥探其奥秘

反过来讲,当我们设计架构时,应该列出我们的核心,围绕核心做上层设计。


第一遍刷


相关文章
|
2月前
|
Java 数据库连接 应用服务中间件
Spring5源码(39)-Aop事物管理简介及编程式事物实现
Spring5源码(39)-Aop事物管理简介及编程式事物实现
33 0
|
2月前
|
Java Spring
Spring 源码阅读 72:基于 CGLIB 的 AOP 代理的原理(2)- 拦截器的查找与执行
【1月更文挑战第7天】本文分析了基于 CGLIB 的 AOP 代理如何查找和执行拦截器链,其主要的逻辑在 DynamicAdvisedInterceptor 的intercept方法执行。
44 1
|
17天前
|
监控 Java Spring
自定义注解+AOP切面日志+源码
自定义注解+AOP切面日志+源码
19 1
|
27天前
|
Java Spring
【JavaEE进阶】 Spring AOP源码简单剖析
【JavaEE进阶】 Spring AOP源码简单剖析
|
2月前
|
Java Spring
Spring 源码阅读 71:基于 CGLIB 的 AOP 代理的原理(1)- DynamicAdvisedInterceptor 分析
【1月更文挑战第6天】本文分析了基于 CGLIB 的 AOP 代理对象,是通过一个 DynamicAdvisedInterceptor 类型的 Callback 来完成 AOP 增强逻辑处理的,DynamicAdvisedInterceptor 通过实现 MethodInterceptor 接口的intercept方法来处理 AOP 增强逻辑。下一篇,将重点分析这个方法的原理。
69 7
|
2月前
Spring5源码(31)-基于@AspectJ的AOP
Spring5源码(31)-基于@AspectJ的AOP
29 0
|
2月前
|
Java Spring
Spring5源码(30)-基于Schema的AOP
Spring5源码(30)-基于Schema的AOP
26 0
|
2月前
|
Java Spring
Spring5源码(28)-Aop知识点回顾以及基于Advice接口的增强实现
Spring5源码(28)-Aop知识点回顾以及基于Advice接口的增强实现
34 0
|
2月前
|
Java Spring
【Spring源码】Spring中的AOP底层原理分析
【Spring源码】Spring中的AOP底层原理分析
|
11月前
|
Java Spring