core 实例化接口_「死磕 Spring」—IOC之bean实例化策略:InstantiationStrategy

原文出自:http://cmsblogs.com

作者:作者:chenssy

在开始分析 InstantiationStrategy 之前,我们先来简单回顾下 bean 的实例化过程:

  1. bean 的创建,主要是 AbstractAutowireCapableBeanFactory.doCreateBean() ,在这个方法中有 bean 的实例化、属性注入和初始化过程,对于 bean 的实例化过程这是根据 bean 的类型来判断的,如果是单例模式,则直接从 factoryBeanInstanceCache 缓存中获取,否则调用 createBeanInstance() 创建。
  2. 在 createBeanInstance() 中,如果 Supplier 不为空,则调用 obtainFromSupplier() 实例化 bean。如果 factory 不为空,则调用 instantiateUsingFactoryMethod() 实例化 bean ,如果都不是则调用 instantiateBean() 实例化bean 。但是无论是 instantiateUsingFactoryMethod() 还是 instantiateBean() 最后都一定会调用到 InstantiationStrategy 接口的 instantiate()。

InstantiationStrategy

InstantiationStrategy 接口定义了 Spring Bean 实例化的策略,根据创建对象情况的不同,提供了三种策略:无参构造方法、有参构造方法、工厂方法。如下:

932b16c2f619f1af2d879290dabc1448.png

SimpleInstantiationStrategy

InstantiationStrategy 接口有两个实现类:SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy。SimpleInstantiationStrategy 对以上三个方法都做了简单的实现。

如果是工厂方法实例化,则直接使用反射创建对象,如下:

5e7c88cb534a1e0113c300aa1c86cb21.png

如果是构造方法实例化,则是先判断是否有 MethodOverrides,如果没有则是直接使用反射,如果有则就需要 CGLIB 实例化对象。如下:

c55f5479fcd027f1b8e08c43ac8dc5aa.png

SimpleInstantiationStrategy 对 instantiateWithMethodInjection() 的实现任务交给了子类 CglibSubclassingInstantiationStrategy。

MethodOverrides

对于 MethodOverrides,如果读者是跟着小编文章一路跟过来的话一定不会陌生,在 BeanDefinitionParserDelegate 类解析 的时候是否还记得这两个方法:parseLookupOverrideSubElements() 和 parseReplacedMethodSubElements() 这两个方法分别用于解析 lookup-method 和 replaced-method。parseLookupOverrideSubElements() 源码如下:

更多关于 lookup-method 和 replaced-method 请看:【死磕 Spring】----- IOC 之解析 bean 标签:meta、lookup-method、replace-method

CGLIB 实例化策略

类 CglibSubclassingInstantiationStrategy 为 Spring 实例化 bean 的默认实例化策略,其主要功能还是对父类功能进行补充:其父类将 CGLIB 的实例化策略委托其实现。

31f34a5fc0da26716ead59aaa3ac9978.png

CglibSubclassingInstantiationStrategy 实例化 bean 策略是通过其内部类 CglibSubclassCreator 来实现的。

 protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Constructor> ctor, @Nullable Object... args) { return new CglibSubclassCreator(bd, owner).instantiate(ctor, args); }

创建 CglibSubclassCreator 实例然后调用其 instantiate(),该方法用于动态创建子类实例,同时实现所需要的 lookups(lookup-method、replace-method)。

b00b751123b486318c14d3a706adf5ff.png

调用 createEnhancedSubclass() 为提供的 BeanDefinition 创建 bean 类的增强子类。

1ef9a45df43f2e69ec3f1c8fd2584f15.png

获取子类增强 class 后,如果 Constructor 实例 ctr 为空,则调用默认构造函数(BeanUtils.instantiateClass())来实例化类,否则则根据构造函数类型获取具体的构造器,调用 newInstance() 实例化类。在 createEnhancedSubclass() 我们注意两行代码:

enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));enhancer.setCallbackTypes(CALLBACK_TYPES);

通过 MethodOverrideCallbackFilter 来定义调用 callback 类型,MethodOverrideCallbackFilter 是用来定义 CGLIB 回调过滤方法的拦截器行为,它继承 CglibIdentitySupport 实现 CallbackFilter 接口, CallbackFilter 是 CGLIB 的一个回调过滤器,CglibIdentitySupport 则为 CGLIB 提供 hashCode() 和 equals() 方法,以确保 CGLIB 不会为每个 bean 生成不同的类。MethodOverrideCallbackFilter 实现 CallbackFilter accept():

c5f9b8b57c371529e0bf72344ef5dc75.png

根据 BeanDefinition 中定义的 MethodOverride 不同,返回不同的值, 这里返回的 PASSTHROUGH 、LOOKUP_OVERRIDE、METHOD_REPLACER 都是 Callbak 数组的下标,这里对应的数组为 CALLBACK_TYPES 数组,如下:

 private static final Class>[] CALLBACK_TYPES = new Class>[] {NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};

这里又定义了两个熟悉的拦截器 :LookupOverrideMethodInterceptor 和 ReplaceOverrideMethodInterceptor,两个拦截器分别对应两个不同的 callback 业务:

LookupOverrideMethodInterceptor

ec546bab2a18623041be4a4620a9cf9d.png

ReplaceOverrideMethodInterceptor

53730484b9d12010358076e95226121d.png

通过这两个拦截器,再加上这篇博客:【死磕 Spring】----- IOC 之解析 bean 标签:meta、lookup-method、replace-method,是不是一道绝佳的美食。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值