3. 基于Cglib实现含构造函数的类实例化策略
3. 基于Cglib实现含构造函数的类实例化策略
对照子工程 lqf-spring-step-03
工程结构

Spring Bean 容器类关系,如图:

主要是在现有工程中添加 InstantiationStrategy 实例化策略接口,以及补充相应的 getBean 入参信息,让外部调用时可以传递构造函数的入参并顺利实例化。
设计
技术设计主要考虑两部分,一个是串流程从哪合理的把构造函数的入参信息传递到实例化操作里,另外一个是怎么去实例化含有构造函数的对象。

- 在 BeanFactory 中添加
Object getBean(String name, Object... args)接口,这样就可以在获取 Bean 时把构造函数的入参信息传递进去了。 - 另外一个核心的内容是使用什么方式来创建含有构造函数的 Bean 对象呢?这里有两种方式可以选择,一个是基于 Java
本身自带的方法DeclaredConstructor,另外一个是使用 Cglib 来动态创建 Bean 对象。
实现
新增 getBean 接口
源码详见: lqf.springframework.beans.factory.BeanFactory#getBean(String name, Object... args) 及其实现
- BeanFactory 中重载了一个含有入参信息 args 的 getBean 方法,这样就可以方便的传递入参给构造函数实例化了。
定义实例化策略接口
源码详见: lqf.springframework.beans.factory.support.InstantiationStrategy
- 在实例化接口 instantiate 方法中添加必要的入参信息,包括:beanDefinition、 beanName、ctor、args。
- 其中 Constructor 你可能会有一点陌生,它是 java.lang.reflect 包下的 Constructor
类,里面包含了一些必要的类信息,有这个参数的目的就是为了拿到符合入参信息相对应的构造函数。 - 而 args 就是一个具体的入参信息了,最终实例化时候会用到。
JDK 实例化
源码详见: lqf.springframework.beans.factory.support.SimpleInstantiationStrategy
- 首先通过 beanDefinition 获取 Class 信息,这个 Class 信息是在 Bean 定义的时候传递进去的。
- 接下来判断 ctor 是否为空,如果为空则是无构造函数实例化,否则就是需要有构造函数的实例化。
这里我们重点关注有构造函数的实例化,实例化方式为 clazz.getDeclaredConstructor(ctor.getParameterTypes()).newInstance(args);
把入参信息传递给 newInstance 进行实例化。
Cglib 实例化
源码详见: lqf.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy
- 其实 Cglib 创建有构造函数的 Bean 也非常方便,在这里我们更加简化的处理了,不过目前的方式并不会影响创建。
创建策略调用
源码详见: lqf.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
- 首先在 AbstractAutowireCapableBeanFactory
抽象类中定义了一个创建对象的实例化策略属性类InstantiationStrategy instantiationStrategy,这里选择了 Cglib 的实现类。 - 接下来抽取
createBeanInstance方法,在这个方法中需要注意 Constructor 代表了你有多少个构造函数,通过
beanClass.getDeclaredConstructors() 方式可以获取到你所有的构造函数,是一个集合。 - 接下来就需要循环比对出构造函数集合与入参信息
args的匹配情况,这里我们对比的方式比较简单,只是一个数量对比,而实际
Spring 源码中还需要比对入参类型,否则相同数量不同入参类型的情况,就会抛异常了。
总结
- 主要以完善实例化操作,增加 InstantiationStrategy 实例化策略接口,并新增了两个实例化类。
- 从不断的完善增加需求可以看到的,当代码结构设计的较为合理的时候,就可以非常容易且方便的进行扩展不同属性的类职责,而不会因为需求的增加导致类结构混乱。所以在业务需求实现的过程中,也要尽可能的去考虑一个良好的扩展性以及拆分好类的职责。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 iAuzre
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果
音乐天地