欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpingAOP源码研究

程序员文章站 2022-03-03 09:14:17
...

     如果之前没有读过Spring源码,建议先看一下我之前写的一个实现AOP的小demo

 

 

     在看SpingAOP源码之前先简单说一下SpingIOC的实现机制。SpingIOC的中最核心的接口是BeanFactory它更像是IOC容器的一个最基本的功能说明书,它有一个底层的实现类DefaultListableBeanFactory这个类基本上实现了BeanFactory体系中的所有重要功能,只有就是我们所熟悉的ApplicationContext。它是在BeanFactory的基础上做了扩展。继承了MessageSource, ApplicationEventPublisher, ResourcePatternResolver等接口以增强除BeanFactory基本功能之外的功能。ApplicationContext的子类基本上使用的就是DefaultListableBeanFactory。

 

IOC容器的初始化步骤:

     1> 定位Resource资源

     2> 创建DefaultListableBeanFactory

     3> 创建处理资源的BeanDefinitionReader

     4> 将Resource解析为Document

     5> 将Document解析为Spring定义的内部数据结构BeanDefinition

     6> 将BeanDefinition注册到Factory的CurrentHashMap中

     7> 创建对象(BeanFactory,Constructor,CGLIB)

     8> 解决依赖关系注入Property(期间会创建所有直接依赖或者间接依赖的类,直到这些类都创建并初始化完成之后,主类才会初始化完成)

     9> 将Bean注册到DefaultSingletonBeanRegistry的ConcurrentHashMap中 SpingIOC是非常强大的强大的副作用就是代码不容易理解。所以说肯定是没有我之前写的那个AOP小Demo好理解了。首先来看AOP通知接口的体系结构。

 

     SpingIOC是非常强大的强大的副作用就是代码不容易理解。所以说肯定是没有我之前写的那个AOP小Demo好理解了。首先来看AOP通知接口的体系结构。
       SpingAOP源码研究
            
    
    博客分类: Spring springaop
 

之后是切入点:

   
SpingAOP源码研究
            
    
    博客分类: Spring springaop

还有一个Advisor(通知器),它用来将Advice和Pointcut组织在一起


SpingAOP源码研究
            
    
    博客分类: Spring springaop

  想要调用代理方法,必须要先有代理对象,那么代理对象是在哪产生的?代理对象其实是在一个处理器AbstractAutoProxyCreator中产生的。用过Spring中处理器的人肯定知道实现BeanPostProcessor接口,然后覆盖postProcessBeforeInitialization,postProcessAfterInitialization两个方法就可以在bean执行init方法前后来处理逻辑了。其实现原理其实很简单,在初始化Bean时可以看到如下代码


SpingAOP源码研究
            
    
    博客分类: Spring springaop
 分别是前置处理,init方法调用,后置处理。看一下生成代理对象类AbstractAutoProxyCreator的类签名


SpingAOP源码研究
            
    
    博客分类: Spring springaop
 
SpingAOP源码研究
            
    
    博客分类: Spring springaop
 

     这样明白了,其实AbstractAutoProxyCreator类就是处理器。如果一个Bean需要创建代理对象的话,就会在这个Bean的init方法执行完之后调用后置处理器创建。创建完之后就会被放置到AbstractAutoProxyCreator类中的一个ConcurrentHashMap中


SpingAOP源码研究
            
    
    博客分类: Spring springaop
 

由于我的目标对象实现了接口所以使用的是JDK代理,否则的话会使用CGLIB代理。


SpingAOP源码研究
            
    
    博客分类: Spring springaop

这是最核心的类,所有被代理的方法都会调用它的invoke方法其中有一个字段

 

	/** Config used to configure this proxy */
	private final AdvisedSupport advised;

 下面是它的截图

 


SpingAOP源码研究
            
    
    博客分类: Spring springaop

 

 

只要搞定它是怎么来的,就会知道通知,切入点,目标类是怎么产生的。

想向下追两个方法都很有用

 

SpingAOP源码研究
            
    
    博客分类: Spring springaop
 

在这里判断了是使用CGLIB创建代理还是JDK创建代理

 

SpingAOP源码研究
            
    
    博客分类: Spring springaop
 

可以看到之前那个万能的字段其实是ProxyCrentorSupport类的实例,还记得之前创建代理的AbstractAutoProxyCreator吗,它们有着共同的基类。ProxyConfig为它的子类提供了配置属性。

 


SpingAOP源码研究
            
    
    博客分类: Spring springaop

 

下面就要追一下这两个类之间是怎么建立关系的。上图调用createAopProxy(this)函数最开始的调用者是AbstractAutoProxyCreator也就是说这个this其实是ProxyFactory的实例


SpingAOP源码研究
            
    
    博客分类: Spring springaop



SpingAOP源码研究
            
    
    博客分类: Spring springaop

 

 

可以看到ProxyFactory又是ProxyCreatorSupport的子类。

那么proxyFactory又是怎么来的?


SpingAOP源码研究
            
    
    博客分类: Spring springaop
 

 

这样也就建立了ProxyCrentorSupport类与AbstractAutoProxyCreator的关系 。也就是说ProxyCrentorSupport在创建代理的工厂AbstractAutoProxyCreator与代理类之间建立了一个桥梁,真正有用的数据像通知,切入点,目标类等最初还是AbstractAutoProxyCreator提供的。ProxyCrentorSupport也起到屏蔽AbstractAutoProxyCreator中的一些敏感信息,防止被代理类获取到作用。ProxyCrentorSupport还是一个抽象工厂,是非常经典的抽象工厂模式的应用。

可以稍微追一下advisor是从哪来的


SpingAOP源码研究
            
    
    博客分类: Spring springaop


 现在来看JdkDynamicAopProxy中invoke是怎么执行的。首先它会创建一个ReflectiveMethodInvocation实例,然后让这个实例来调用proceed方法。这个ReflectiveMethodInvocation就相当于之前小Demo的ApplicationFilterChain。其结构如下


SpingAOP源码研究
            
    
    博客分类: Spring springaop


 其中每一个advice被调用时都会把自身实例传入其中,然后调完通知方法之后就会重新调用ReflectiveMethodInvocation实例的proceed方法。这样便形成了回调机制,也就实现了AOP的功能(跟我的小demo原理一样)。其他通知与前置通知类似,异常通知是直接让你执行一个try…catch块环绕的代码,这样报错之后就会被处理。至于最终通知是把proceed放在了一个try…finally中。

 

  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 7 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 24.3 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 9.8 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 4.6 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 36.6 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 12.2 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 41.8 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 20.8 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 20.4 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 48.6 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 44.8 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 23.9 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 24 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 13.2 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 12.7 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 74.1 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 16.2 KB
  • SpingAOP源码研究
            
    
    博客分类: Spring springaop
  • 大小: 25.4 KB
相关标签: spring aop