Spring 遵循原型设计模式的弹簧原型

Spring 遵循原型设计模式的弹簧原型,spring,design-patterns,prototype-pattern,Spring,Design Patterns,Prototype Pattern,Spring提供了bean范围作为“原型”。意味着每当应用程序中需要bean时,Spring容器将创建一个新的bean实例。 是不是也遵循原型设计模式? 它是否只创建一次对象,并在随后的请求中调用已创建对象上的clone()方法来创建新对象 另外,如果有人可以提供JDK、Spring、Hibernate或任何J2EE框架中的原型示例。Spring不使用原型模式,而是使用反射。 另外,为了使用clone(),它必须以某种方式子类化一个bean,因为clone()是受保护的,所以它也不使用clone

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


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

Spring不使用原型模式,而是使用反射。 另外,为了使用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);
                    ...
                }
                ...

    }
    ...
}
公共对象实例化(RootBeanDefinition beanDefinition、字符串beanName、BeanFactory所有者){
if(beanDefinition.getMethodOverrides().isEmpty()){
建造商房屋;
已同步(beanDefinition.constructorArgumentLock){
constructorToUse=(Constructor)beanDefinition.ResolvedConstructor或FactoryMethod;
...
constructorToUse=clazz.getDeclaredConstructor((Class[])null;
...
}
...
}
...
}

因此,prototype一词被用来表示在每次调用getBean时,您都会得到一个具有相同属性的新实例。然而,这不仅仅是对构造函数的简单调用,因为您将得到一个连接了所有依赖项和其他属性的bean,所以从某种意义上说,它是一个原型。或者至少它非常符合这个概念

我没有深入研究Spring源代码,但我认为Spring中具有
prototype
作用域的bean不是使用
clone()
方法创建的,因为它不是强制为这些bean实现
Cloneable
接口的

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


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

没有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);
}

不可以。Spring示波器,如原型单音不严格遵循设计模式。作用域的命名用于直观地提示容器提供的行为

通过这种方式,您可以在容器内创建“单例”模式,并在容器外创建另一个对象。类似地,“原型”模式不必实现“克隆”功能

您也可以查看此链接:

这里有更详细的解释:

我首先要说的是,这应该作为两个独立的问题来问。对于您的第一个示例,我还没有深入研究,但是如果它确实使用了原型模式,我会非常惊讶。关于你的第二个问题:
BeanUtils.instantiateClass(constructorToUse);