Spring中常用的设计模式:单例模式

在Spring中,Bean可以被定义为两种模式:prototype(原型)和singleton(单例)。

  • singleton(单例)
    只有一个共享的实例存在,所有对这个Bean的请求都会返回这个唯一的实例。
  • prototype(原型)
    对这个Bean的每次请求都会创建一个新的bean实例,类似于new。

Spring依赖注入Bean实例默认是单例的。
Spring的依赖注入(包括lazy-init方式)都是发生在 AbstractBeanFactory 的 getBean 里。

getBean 的 doGetBean 方法调用 getSingleton 进行Bean的创建。lazy-init方式(lazy-init=“false”),在用户向容器第一次索要Bean时进行调用;非lazy-init方式(lazy-init=“true”),在容器初始化时候进行调用。

  • 同步线程安全的单例核心代码
/**
     * Return the (raw) singleton object registered under the given name.
     * <p>Checks already instantiated singletons and also allows for an early
     * reference to a currently created singleton (resolving a circular reference).
     * @param beanName the name of the bean to look for
     * @param allowEarlyReference whether early references should be created or not
     * @return the registered singleton object, or {@code null} if none found
     */
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

spring依赖注入时,使用了双重判断加锁的单例模式。

首先从缓存singletonObjects(实际上是一个map)中获取Bean实例,如果为null,对缓存singletonObjects加锁,然后再从缓存中获取Bean,如果继续为null,就创建一个Bean。

这样双重判断,能够避免在加锁的瞬间,有其他依赖注入引发bean实例的创建,从而造成重复创建的结果。

猜你喜欢

转载自blog.csdn.net/sinat_34341162/article/details/84111353