BeanFactory#getBean(String name) 是线程安全的嘛❓

318 阅读3分钟

先回答:是线程安全的,多线程竞争的时候,通过 synchronized 加锁

这里不讨论scope 是prototype 的bean,因为每次getBean() 的时候获取的都是一个新的实例,不存在线程安不安全

这里只重点讨论 scope是singleton

从 AbstractBeanFactory.class 中的getBean(String name) 开始分析

 @Override
   public Object getBean(String name) throws BeansException {
     return doGetBean(name, null, null, false);
   }
 protected <T> T doGetBean(
       String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
       throws BeansException {
 ​
     String beanName = transformedBeanName(name);
     Object beanInstance;
 ​
     // 检查缓存中是否存在 singleton的bean
     Object sharedInstance = getSingleton(beanName);
     if (sharedInstance != null && args == null) {
       if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
           logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
               "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
           logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
       }
       beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
     }
 ​
     else {
       // Fail if we're already creating this bean instance:
       // We're assumably within a circular reference.
       if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
       }
 ​
       // Check if bean definition exists in this factory.
       BeanFactory parentBeanFactory = getParentBeanFactory();
       if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory abf) {
           return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
         }
         else if (args != null) {
           // Delegation to parent with explicit args.
           return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else if (requiredType != null) {
           // No args -> delegate to standard getBean method.
           return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {
           return (T) parentBeanFactory.getBean(nameToLookup);
         }
       }
 ​
       if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
       }
 ​
       StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
           .tag("beanName", name);
       try {
         if (requiredType != null) {
           beanCreation.tag("beanType", requiredType::toString);
         }
         // 这里的 mergeedLoclBeanDinition 也是通过 synchronized 加了锁
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);
 ​
         // Guarantee initialization of beans that the current bean depends on.
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
           for (String dep : dependsOn) {
             if (isDependent(beanName, dep)) {
               throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                   "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
             }
             registerDependentBean(dep, beanName);
             try {
               // 去递归依赖
               getBean(dep);
             }
             catch (NoSuchBeanDefinitionException ex) {
               throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                   "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
             }
           }
         }
 ​
         // 创建bean实例
         if (mbd.isSingleton()) {
           sharedInstance = getSingleton(beanName, () -> {
             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;
             }
           });
           // 这里的 getObjectForBeanInstance 判断是不是走 getObject等操作,这里也加了  synchronized,锁定的也是 this.singletonObjects
           beanInstance = 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);
           }
           beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }
 ​
         else {
           String scopeName = mbd.getScope();
           if (!StringUtils.hasLength(scopeName)) {
             throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
           }
           Scope scope = this.scopes.get(scopeName);
           if (scope == null) {
             throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
           }
           try {
             Object scopedInstance = scope.get(beanName, () -> {
               beforePrototypeCreation(beanName);
               try {
                 return createBean(beanName, mbd, args);
               }
               finally {
                 afterPrototypeCreation(beanName);
               }
             });
             beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
           }
           catch (IllegalStateException ex) {
             throw new ScopeNotActiveException(beanName, scopeName, ex);
           }
         }
       }
       catch (BeansException ex) {
         beanCreation.tag("exception", ex.getClass().toString());
         beanCreation.tag("message", String.valueOf(ex.getMessage()));
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
       }
       finally {
         beanCreation.end();
       }
     }
 ​
     return adaptBeanInstance(name, beanInstance, requiredType);
   }

如果bean 存在,则读取,即getSingleton(String beanName) 方法。

   @Override
   @Nullable
   public Object getSingleton(String beanName) {
     return getSingleton(beanName, true);
   }
 ​
   @Nullable
   protected Object getSingleton(String beanName, boolean allowEarlyReference) {
     // Quick check for existing instance without full singleton lock
     Object singletonObject = this.singletonObjects.get(beanName);
     if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
       singletonObject = this.earlySingletonObjects.get(beanName);
       if (singletonObject == null && allowEarlyReference) {
         // 这里判断如果在 singletonObjects 和 earlySingletonObjects 里面都没找到,而且允许循环依赖,这个时候如果 singletonFactories 存在创建beanName 的ObjectFactory 就要走bean创建了,而这里加了一个 synchronized,保证了线程安全。
         synchronized (this.singletonObjects) {
           // Consistent creation of early reference within full singleton lock
           singletonObject = this.singletonObjects.get(beanName);
           if (singletonObject == null) {
             singletonObject = this.earlySingletonObjects.get(beanName);
             if (singletonObject == null) {
               ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
               if (singletonFactory != null) {
                 singletonObject = singletonFactory.getObject();
                 this.earlySingletonObjects.put(beanName, singletonObject);
                 this.singletonFactories.remove(beanName);
               }
             }
           }
         }
       }
     }
     return singletonObject;
   }

如果上面的getSingleton(String beanName) 返回的是null,即来到了getSingleton 方法,走创建流程

   public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
     Assert.notNull(beanName, "Bean name must not be null");
     // 这里是当没有找到Bean时候的创建逻辑,singletonFactory 的getObject 获取bean,可以看到这里也有 synchronized,保证了创建时候的线程安全。
     synchronized (this.singletonObjects) {
       Object singletonObject = this.singletonObjects.get(beanName);
       if (singletonObject == null) {
         if (this.singletonsCurrentlyInDestruction) {
           throw new BeanCreationNotAllowedException(beanName,
               "Singleton bean creation not allowed while singletons of this factory are in destruction " +
               "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
         }
         if (logger.isDebugEnabled()) {
           logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
         }
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
           this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
           singletonObject = singletonFactory.getObject();
           newSingleton = true;
         }
         catch (IllegalStateException ex) {
           // Has the singleton object implicitly appeared in the meantime ->
           // if yes, proceed with it since the exception indicates that state.
           singletonObject = this.singletonObjects.get(beanName);
           if (singletonObject == null) {
             throw ex;
           }
         }
         catch (BeanCreationException ex) {
           if (recordSuppressedExceptions) {
             for (Exception suppressedException : this.suppressedExceptions) {
               ex.addRelatedCause(suppressedException);
             }
           }
           throw ex;
         }
         finally {
           if (recordSuppressedExceptions) {
             this.suppressedExceptions = null;
           }
           afterSingletonCreation(beanName);
         }
         if (newSingleton) {
           addSingleton(beanName, singletonObject);
         }
       }
       return singletonObject;
     }
   }

所以从读取的方式还是创建的方式来说,scope是 singleton 的bean 都通过 synchronized (this.singletonObjects) 保证了线程安全。