Spring原型遵循原型设计模式

时间:2014-10-28 13:45:50

标签: spring design-patterns prototype-pattern

Spring将bean范围提供为“Prototype”。意味着只要应用程序中需要bean,Spring容器就会创建一个新的/新的bean实例。 是否遵循原型设计模式? 它只创建一次对象,并在后续请求中调用创建的对象上的clone()方法来创建新对象吗?

此外,如果有人可以在JDK,Spring,Hibernate或任何J2EE框架中提供原型示例。

4 个答案:

答案 0 :(得分:1)

没有spring不使用克隆来创建原型范围的实例。

以下是AbstractBeanFactory.doGetBean()函数的代码片段:

// Create bean instance.
if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
        @Override
        public Object getObject() throws BeansException {
            try {
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
                // Explicitly remove instance from singleton cache: It might have been put there
                // eagerly by the creation process, to allow for circular reference resolution.
                // Also remove any beans that received a temporary reference to the bean.
                destroySingleton(beanName);
                throw ex;
            }
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
    // It's a prototype -> create a new instance.
    Object prototypeInstance = null;
    try {
        beforePrototypeCreation(beanName);
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

createBean方法调用归结为以下代码:

BeanUtils.instantiateClass(constructorToUse);

答案 1 :(得分:0)

Spring不使用Prototype Pattern,它使用反射。 另外,为了使用clone(),它必须以某种方式为bean子类化,因为clone()受到保护,所以它也不使用clone()。

这是来自

的代码片段
org.springframework.beans.factory.support.SimpleInstantiationStrategy

您可以在其中看到java.lang.reflect.Constructor和java.lang.Class反射方法的使用:

public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {

    if (beanDefinition.getMethodOverrides().isEmpty()) {
        Constructor<?> constructorToUse;
        synchronized (beanDefinition.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
                    ...
                        constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);
                    ...
                }
                ...

    }
    ...
}

因此术语原型用于表示在每次调用getBean时,您将获得具有相同属性的新实例。这不仅是对构造函数的简单调用,因为你将获得一个所有依赖关系连接的bean和其他属性设置,所以从某种意义上说它是一个原型。或者至少它非常适合这个概念。

答案 2 :(得分:0)

我没有深入研究Spring源代码,但我认为Spring中具有prototype范围的Beans不是使用clone()方法创建的,因为实现Cloneable接口不是必需的那些豆子。

此外,假设它使用clone()创建它们。如果有人期待深拷贝而不是浅拷贝,那将是危险的。

您可以随时测试并找到答案。

答案 3 :(得分:0)

没有。诸如 prototype singletone 之类的Spring范围不遵循严格的设计模式。范围的命名用于直观地建议行为容器提供。

这样,您可以在容器中拥有“单例”模式,并在容器外部创建另一个对象。类似地,“原型”模式不必实现“克隆”功能。

您可能也想查看此链接:
Singleton design pattern vs Singleton beans in Spring container

这里有更详细的解释:
https://springframework.guru/gang-of-four-design-patterns/prototype-pattern/