阿八博客
  • 100000+

    文章

  • 23

    评论

  • 20

    友链

  • 最近新加了很多技术文章,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

Spring5源码解析7-ConfigurationClassPostProcessor (下)

欢迎来到阿八个人博客网站。本 阿八个人博客 网站提供最新的站长新闻,各种互联网资讯。 喜欢本站的朋友可以收藏本站,或者加QQ:我们大家一起来交流技术! URL链接:https://www.abboke.com/jsh/2019/1010/116382.html

ConfigurationClassPostProcessor继承了BeanDefinitionRegistryPostProcessor接口,它实现了postProcessBeanDefinitionRegistry和其父类的BeanFactoryPostProcessor#postProcessBeanFactory方法

关于postProcessBeanDefinitionRegistry方法的解析可以参看:Spring5 源码学习 (5) ConfigurationClassPostProcessor (上)

现在我们来看一下ConfigurationClassPostProcessor#postProcessBeanFactory方法的源码

ConfigurationClassPostProcessor#postProcessBeanFactory

调用时机

ConfigurationClassPostProcessor#postProcessBeanFactory方法也在refresh();方法中执行invokeBeanFactoryPostProcessors(beanFactory);方法时被调用的

源码解析

主要做了两件事:

对配置类进行增强创建ImportAwareBeanPostProcessor 来支持ImportAware接口

主要来看一下对配置类进行增强方法enhanceConfigurationClasses(beanFactory);的源码

enhanceConfigurationClasses(beanFactory)增强 Full Configuration

Spring会对Full Configuration 进行代理,拦截@Bean方法,以确保正确处理@Bean语义
这个增强的代理类就是在enhanceConfigurationClasses(beanFactory)方法中产生的,源码如下:

获取所有为FullConfigurationClass的BeanDefinition(即标注@Configuration的配置类),然后依次调用enhancer.enhance(configClass, this.beanClassLoader);方法,对配置类进行增强,将方法返回Class<?> enhancedClass的设置到BeanDefinition中(eanDef.setBeanClass(enhancedClass);),之后Spring创建该BeanDefinition时就会使用这个增强类来创建

下面是enhancer.enhance(configClass, this.beanClassLoader);方法源码:

创建Full Configuration增强类

具体来看一下newEnhancer(configClass, classLoader方法,这个方法负责创建Full Configuration增强类

BeanMethodInterceptor:负责拦截@Bean方法的调用,以确保正确处理@Bean语义
BeanFactoryAwareMethodInterceptor:负责拦截 BeanFactoryAware#setBeanFactory方法的调用,因为增强的配置类实现了EnhancedConfiguration接口(也就是实现了BeanFactoryAwar接口)

设置增强Callback

下面,我们就以AppConfig为例,来学习增强Callback相关源码

BeanMethodInterceptor

主要作用是:拦截@Bean方法的调用,以确保正确处理@Bean语义
当调用@Bean方法时,就会被以下代码所拦截:

enhancedConfigInstance是配置类的增强对象
从增强对象中获取beanFactorybeanName
举个例子:当Spring调用name()方法时,beanName就是name
检查容器中是否存在对应的FactoryBean,如果存在,则创建一个增强类,来代理getObject()的调用
在本示例中,如果读者将name()方法注释删掉之后程序并不会执行到这一步
因为Spring调用getUserBean()方法时,容器中并没有存在对应的FactoryBean
因为只有第二次调用getUserBean()方法容器中才会存在对应的FactoryBean
判断当时执行的方法是否为@Bean方法本身,如果是,则直接调用该方法,不做增强拦截;否则,则尝试从容器中获取该Bean对象
BeanFactoryAwareMethodInterceptor

BeanFactoryAwareMethodInterceptor方法就比较简单,其作用为拦截 BeanFactoryAware#setBeanFactory的调用,用于获取BeanFactory对象

输出增强类class文件

最后,再补充说明一点,我们可以通过如下配置来获取Spring为我们生成的CGLIB代理增强类的class文件:

源码注释GITHUB地址:https://github.com/shenjianen...

欢迎关注公众号,一起学习成长

相关文章

暂住......别动,不想说点什么吗?
  • 全部评论(0
    还没有评论,快来抢沙发吧!