Spring 创建Bean时,可以通过scope指定singletone单例还是prototype原型,这里的prototype是使用原型设计模式实现的吗?
通过跟踪Spring 创建Bean的源码,入口是org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean,发现在指定为prototype时,创建Bean的方式最终还是根据Bean的定义信息来创建的,并不是从已有的实例信息中clone出一个新实例。
那Spring为什么不采用原型模式来创建Bean呢?
原型模式的定义是:以实例信息来指定对象类型,通过clone的方式来创建新对象。这里的实例信息就是原型。
原型模式的难点是clone的实现,虽然Java原生支持Object#clone接口,但要求子类需要实现Cloneable接口,并重写clone方法,由于clone得到的对象必须是完全的独立的,这就要求clone方法需要支持深度拷贝,深度拷贝得考虑类中的可变属性循环依赖,这几乎是难以实现的。网上还流行说用序列化的形式实现clone,这也不靠谱,首先对象序列化存在性能问题,其次在Java中如果要实现标准对象序列化,需要实现Serializable接口,类的属性也要求支持序列化,这个要求就几乎不可能实现,因为有时候我们类的属性是来自第三方系统。
所以Spring并没有使用原型设计模式来实现prototype,只是蹭了个概念。
哪些场景适合使用原型模式?
创建对象比较困难或者没办法获得静态类信息,并且系统中对象的类可以提供clone实现。