spring 创建bean过程

本文详细解析了Spring框架中Bean的创建过程,包括ContextLoaderListener的启动,容器的刷新,非懒加载单例的初始化。重点讨论了Spring如何解决循环依赖问题,如属性循环依赖和构造函数循环依赖,通过三种不同的缓存机制来避免无限循环。对于属性循环依赖,Spring使用了早期singletonObjects、singletonFactories和singletonObjects三个缓存进行管理。而构造函数循环依赖则会直接报错。此外,多例Bean的创建不会进行单例验证,每次请求都会创建新的实例。

1 ContextLoaderListener

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
   public ContextLoaderListener(WebApplicationContext context) {
      super(context);
   }
   @Override
   public void contextInitialized(ServletContextEvent event) {
      initWebApplicationContext(event.getServletContext());
   }
   @Override
   public void contextDestroyed(ServletContextEvent event) {
      closeWebApplicationContext(event.getServletContext());
      ContextCleanupListener.cleanupAttributes(event.getServletContext());
   }

}
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
   if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
      throw new IllegalStateException(
            "Cannot initialize context because there is already a root application context present - " +
            "check whether you have multiple ContextLoader* definitions in your web.xml!");
   }

   Log logger = LogFactory.getLog(ContextLoader.class);
   servletContext.log("Initializing Spring root WebApplicationContext");
   if (logger.isInfoEnabled()) {
      logger.info("Root WebApplicationContext: initialization started");
   }
   long startTime = System.currentTimeMillis();

   try {
      // Store context in local instance variable, to guarantee that
      // it is available on ServletContext shutdown.
      if (this.context == null) {
         //创建WebApplicationContext对象,
         //如果在xml中配置了参数contextClass的话,取参数值定义的class
         //如果xml未配置参数,那么读取spring配置文件ContextLoader.properties定义的class
         //org.springframework.web.context.support.XmlWebApplicationContext
         //XmlWebApplicationContext实现了WebApplicationContext接口
         this.context = createWebApplicationContext(servletContext);
      }
      if (this.context instanceof ConfigurableWebApplicationContext) {
         //强转成ConfigurableWebApplicationContext
         ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
         //容器未启动
         if (!cwac.isActive()) {
            // The context has not yet been refreshed -> provide services such as
            // setting the parent context, setting the application context id, etc
            if (cwac.getParent() == null) {
               // The context instance was injected without an explicit parent ->
               // determine parent for root web application context, if any.
               // 这里spring5之后已经默认返回null
               ApplicationContext parent = loadParentContext(servletContext);
               cwac.setParent(parent);
            }
            //配置并刷新容器,这里读取了xml配置中的spring配置文件名称
            configureAndRefreshWebApplicationContext(cwac, servletContext);
         }
      }
						//把整个容器信息放入到servletContext属性中
   
   servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

      ClassLoader ccl = Thread.currentThread().getContextClassLoader();
      if (ccl == ContextLoader.class.getClassLoader()) {
         currentContext = this.context;
      }
      else if (ccl != null) {
         currentContextPerThread.put(ccl, this.context);
      }

      if (logger.isDebugEnabled()) {
         logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
               WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
      }
      if (logger.isInfoEnabled()) {
         long elapsedTime = System.currentTimeMillis() - startTime;
         logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
      }

      return this.context;
   }
   catch (RuntimeException ex) {
      logger.error("Context initialization failed", ex);
      servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
      throw ex;
   }
   catch (Error err) {
      logger.error("Context initialization failed", err);
      servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
      throw err;
   }
}

2 配置并刷新容器

//配置并刷新容器
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
   //这里setID
   if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
      // The application context id is still set to its original default value
      // -> assign a more useful id based on available information
      String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
      if (idParam != null) {
         wac.setId(idParam);
      }
      else {
         // Generate default id...
         wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
               ObjectUtils.getDisplayString(sc.getContextPath()));
      }
   }
	 //让容器持有ServletContext,ServletContext和容器相互持有对方对象
   wac.setServletContext(sc);
   //读取了xml配置中的spring配置文件名称
   //例如
   //<context-param>
   //     <param-name>contextConfigLocation</param-name>
   //     <param-value>classpath*:applicationContext-aop-annotation.xml</param-value>
   // </context-param>
   String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
   if (configLocationParam != null) {
      wac.setConfigLocation(configLocationParam);
   }

   // The wac environment's #initPropertySources will be called in any case when the context
   // is refreshed; do it eagerly here to ensure servlet property sources are in place for
   // use in any post-processing or initialization that occurs below prior to #refresh
   ConfigurableEnvironment env = wac.getEnvironment();
   if (env instanceof ConfigurableWebEnvironment) {
      ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
   }
	 //所有实现了ApplicationContextInitializer接口的类都会在这一步被调用
   //可以通过web.xml参数化形式globalInitializerClasses和contextInitializerClasses配置
   //也可以通过spi来配置,
   //如果是springboot,也可以main函数启动容器时添加
   customizeContext(sc, wac);
   //真正刷新容器,加载类信息
   wac.refresh();
}

2.1 refresh

@Override
public void refresh() throws BeansException, IllegalStateException {
   //加锁串行
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      //准备阶段,更新容器启动时间,启动状态,读取配置在jvm或者系统中的配置文件然后验证
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      // 告诉子类刷新和初始化 beanFactory DefaultListableBeanFactory实例
      // DefaultListableBeanFactory实现了ConfigurableListableBeanFactory接口
      // loadBeanDefinitions读取bean生成BeanDefinition
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      // 准备bean factory给上下文使用,给beanFactory,set各种属性
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         // 给子类提供的后置处理回调
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         //beanFactory后置
         //调用实现了
         //BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口的实现类
         //方法里做了doGetBean,获取的类实例
         //BeanDefinitionRegistryPostProcessor传递BeanDefinitionRegistry实例
         //BeanFactoryPostProcessor传递ConfigurableListableBeanFactory实例,这里可以修改BeanDefinition定义的bean在实例化之前
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         //把所有实现了BeanPostProcessor接口的类注册到beanFactory中,优先级、排序
         //这里注册了一个容器的process,ApplicationListenerDetector
         //容器通过这个linstener在创建bean之后把bean是否是单例放入到了ApplicationListenerDetector类的属性中做了缓存。
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         //国际化
         initMessageSource();

         // Initialize event multicaster for this context.
         //初始化广播事件
         //实现了ApplicationEventMulticaster接口的类set到当前容器中applicationEventMulticaster
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         //初始化特定上下文子类中的其他特殊bean。
         onRefresh();

         // Check for listener beans and register them.
         //实现了ApplicationListener和ApplicationEvent接口的实现类set到当前容器中applicationEventMulticaster
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         // 初始化非懒加载的单例类
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

2.2 初始化非懒加载的单例类

/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // Initialize conversion service for this context.
   // 加载实现了ConversionService接口的实现类,数据转换
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }

   // Register a default embedded value resolver if no bean post-processor
   // (such as a PropertyPlaceholderConfigurer bean) registered any before:
   // at this point, primarily for resolution in annotation attribute values.
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
   }

   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
   //加载实现了LoadTimeWeaverAware接口的实现类
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes.
   //缓存bean definition
   beanFactory.freezeConfiguration();

   // Instantiate all remaining (non-lazy-init) singletons.
   //实例化非懒加载单例bean
   beanFactory.preInstantiateSingletons();
}
@Override
public void preInstantiateSingletons() throws BeansException {
   if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      //合并BeanDefinition,把于当前beanName有关的BeanDefinition合并到一起返回RootBeanDefinition
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //非抽象类,单例类,非懒加载
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         //是FactoryBean
         if (isFactoryBean(beanName)) {
            //加上前缀,获取FactoryBean实例
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                              ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               //如果是急需初始化的
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            //不是FactoryBean,直接初始化
            getBean(beanName);
         }
      }
   }

   // Trigger post-initialization callback for all applicable beans...
   //实例化后的回调
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
         final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
               smartSingleton.afterSingletonsInstantiated();
               return null;
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

3 doGetBean

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	 //转换BeanName,如果是factoryBean要去掉前缀符号,要真实bean的beanName
   final String beanName = transformedBeanName(name);
   Object bean;

   // Eagerly check singleton cache for manually registered singletons.
   //从单例缓存中获取bean,如果没有就添加到缓存,第一次进入的时候,返回值肯定是null
   Object sharedInstance = getSingleton(beanName);
   //没有参数
   if (sharedInstance != null && args == null) {
      if (logger.isDebugEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      //如果进入到这里,表明不是第一次getBean,
      //先判断是不是FactoryBean,如果name带有&前缀,并且是FactoryBean的话就调用getObject
      //但如果不是FactoryBean,那就直接返回sharedInstance回来
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
		//到else表明肯定是第一次调用了,实例化bean
   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      //判断当前bean是否正在被创建
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      // 去父容器中查找bean,前提是当前容器中不存在这个bean,并且父容器不是空
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         }
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
      }
      //实例化单例非懒加载bean的时候传入的是false
      if (!typeCheckOnly) {
         //标记bean已经初始化
         markBeanAsCreated(beanName);
      }

      try {
         //合并父类所有属性方法
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        //检查当前要实例化bean,是不是抽象类
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         //依赖问题,如果两个类dependsOn了对方,那么就会报错@DependsOn或xml配置
         //有两个map存放以来关系,
         //一个是dependentBeanMap存放被当前bean依赖的bean
         //另一个dependenciesForBeanMap存放当前bean
         //如果bin1和bin2相互依赖,bin1在实例化的时候不会报错,然后registerDependentBean把自己的依赖存放到dependentBeanMap,随后因为依赖了bin2,那么就要递归去实例化bin2,在实例化bin2的时候isDependent判断会报错,因为这个dependentBeanMap被依赖的map里是否有自己,如果有自己说明自己被别人依赖
         //总之依赖的话都是递归查找的,1依赖2依赖3依赖4依赖1,那么最终会在dependentBeanMap里面发现4依赖的1,因为在isDependent里面有递归isDependent的调用,最终会发现2被1依赖了,这样链条就链接上了,最后会报错
        //同样的道理,在后面的createBean方法中也会对构造函数循环依赖做类似的处理
         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);
               }
            }
         }

         // Create bean instance.
         //创建单例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;
               }
            });
            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);
         }

         else {
            String scopeName = mbd.getScope();
            final 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);
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
               "Scope '" + scopeName + "' is not active for the current thread; consider " +
      "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   // Check if required type matches the type of the actual bean instance.
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      }
      catch (TypeMismatchException ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

3.1 创建单例Singleton

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "Bean name must not be null");
   //加锁,单例+实例的map
   synchronized (this.singletonObjects) {
      //查看存放创建出来的实体缓存中是否有当前beanName
      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 + "'");
         }
         //前置检查
         //创建之前验证beanName是否是被排除集合中排除实例化的bean
         //并且是否已经在创建中的beanName集合中了
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
            //执行createBean方法创建bean实例
            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;
            }
            //后置检查,
            //创建之前验证beanName是否是被排除集合中排除实例化的bean
            //并且是否已经在创建中的beanName集合移除成功了
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            //如果创建bean成功,
            //将对象实例添加Map<String, Object> singletonObjects缓存中
            //将beanName从Map<String, ObjectFactory<?>> singletonFactories缓存中移除
            //将beanName从Map<String, Object> earlySingletonObjects缓存中移除
            //将beanName添加到Set<String> registeredSingletons缓存中
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

3.1.1 getObject

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   try {
      //spring配置中存在lookup-mehtod和replace-method,会把数据保存到methodOverrides对象中
      //这里去是否重写父类的方法,
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      //实现了InstantiationAwareBeanPostProcessor接口的类进行调用,
      //InstantiationAwareBeanPostProcessor继承BeanPostProcessor接口
      //需要实现5个人方法,
      //postProcessBeforeInstantiation
      //postProcessAfterInstantiation
      //postProcessPropertyValues
      //postProcessBeforeInitialization
      //postProcessAfterInitialization
      //在这里可以自定义代理类然后返回给容器
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      //如果上面的bean是null,在这里创建bean
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isDebugEnabled()) {
         logger.debug("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}

3.2 doCreateBean

//类AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
  //上面的缓存中没有BeanWrapper
   if (instanceWrapper == null) {
     //创建BeanWrapper实例,BeanWrapper主要功能是对bean实例设置属性的
     //方法里面利用Java-Supplier初始化bean
     //或工厂方法初始化bean
     //或无参数,有参数,默认构造函数等方式构造bean
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   //获取bean实例
   final Object bean = instanceWrapper.getWrappedInstance();
   //获取bean,class,这个class可能是bean本身,也可能是工厂的bean
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            //加锁通知实现了MergedBeanDefinitionPostProcessor接口的实现类,这里有个容器的listener,ApplicationListenerDetector,增加bean是否是单例的缓存
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   //是单例类,允许循环引用,当前bean正在创建
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
         logger.debug("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      //往缓存保存数据
      //this.singletonFactories.put(beanName, singletonFactory);
			//this.earlySingletonObjects.remove(beanName);
			//this.registeredSingletons.add(beanName);
      //
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      //填充bean属性,通过我们设置的Autowire,name或者type的方式来确定使用哪种方式去填充
      //填充期间,检查属性是否是bean,如果就要初始化属性的bean,还要检测循环依赖
      populateBean(beanName, mbd, instanceWrapper);
      //调用配置好的init-method="init"配置,
      //如果不是代理类的话,在调用前后都要调用BeanPostProcessor接口的两个方法
      //postProcessBeforeInitialization和postProcessAfterInitialization
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }
	 //这里做的处理是因为可能在上面调用BeanPostProcessor接口的两个方法会返回bean的实例
   //但是在返回的时候返回的不是当前bean的实例,例如返回了一个Sting类型
   //情况1:调用postProcessBeforeInitialization返回String,在调用init方法时就会报错,
 	 //情况2:调用postProcessAfterInitialization返回String,那么下面的代码就会去生效
   if (earlySingletonExposure) {
      //通过beanName取到缓存的实例
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         //通过BeanPostProcessor接口回调返回的exposedObject如果和当前bean相同,就赋值
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         //如果不一样,看看有没有依赖问题
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            //循环所有引用依赖,准备删除掉
            for (String dependentBean : dependentBeans) {
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            //如果发现有删除不掉的依赖,报错
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,"错误消息");
            }
         }
      }
   }

   // Register bean as disposable.
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

4 spring解决循环依赖

4.1 属性循环依赖

先看一下解决依赖之前spring提供的三种缓存

/** Cache of singleton objects: bean name --> bean instance */
//缓存1,保存的是beanName与bean实体,并且实体类各种属性也填充完毕的
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
//缓存2,保存的是beanName与ObjectFactory接口的具体实现
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name --> bean instance */
//缓存3,保存的是beanName与bean实体,不过这个实体并不是各种属性都填充完毕的完整bean
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

现在详细看这三种缓存保存数据的节点

singletonObjects是在bean实体创建完毕,并且已经填充各种属性之后,put进去的。

singletonFactories是在bean初始化完成之后,填充属性之前,put进去的。

earlySingletonObjects的put有点苛刻,前提是singletonObjects没有该bean实例,然后在缓存2里面存在该bean的情况下才做的put。

例如,bin1依赖bin2,bin2依赖bin3,bin3依赖bin1。这样的一个依赖关系,

容器

  • 初始化bin1,singletonFactories去put了bin1,填充属性发现依赖bin2。

  • 初始化bin2,singletonFactories去put了bin2,填充属性发现依赖bin3。

  • 初始化bin3,singletonFactories去put了bin3,填充属性发现依赖bin1。

  • 初始化bin1。

此时初始化这个bin1就是解决循环依赖的关键

singletonFactories的map里面分别保存了bin1,bin2,bin3,

在getBean->doGetBean方法的最开始有这段代码,这里失去检查缓存中是否已经存在了当前bean

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
@Override
@Nullable
public Object getSingleton(String beanName) {
   return getSingleton(beanName, true);
}
@Nullable
//比如说现在程序执行到了第四步,再次初始化bin1
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
        //那么再进入到这个方法的时候this.earlySingletonObjects.get(beanName);肯定是空值
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
           //这里会取出之前保存的bin1的ObjectFactory,
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
              //取出bin1的实例
               singletonObject = singletonFactory.getObject();
              //添加到缓存如果后面再有其他bean依赖了earlySingletonObjects里面的bean,会在上面判断的时候直接返回
               this.earlySingletonObjects.put(beanName, singletonObject);
              //清除ObjectFactory
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return singletonObject;
}

比如说现在程序执行到了第四步,再次初始化bin1

那么再进入到这个方法的时候this.earlySingletonObjects.get(beanName);肯定是空值,程序继续往下

this.singletonFactories.get(beanName);的时候会取出之前保存的bin1的ObjectFactory,

发现了ObjectFactory!=null,因为在singletonFactories添加bin1的时候,斌bin1已经初始化过一次了

那么就执行singletonFactory.getObject()取出bin1的实例,

处理完之后就直接返回bin1实例,不会再继续往下,重复创建bin1实例了。而是直接把bin3的依赖bin1直接给填充上了,并递归返回。

ps: 现在看来其实用2种缓存应该也是可以解决这个依赖的问题,但为什么spring偏偏用了3种缓存来处理呢?

后来跟踪代码发现在循环依赖引用触发的时候singletonFactory.getObject();会执行一个callback,所有实现了

SmartInstantiationAwareBeanPostProcessor接口的类都会触发这个回调,在返回bean之前。而且为了保证只回调一次,所以用了这个earlySingletonObjects。

4.2 构造函数循环依赖

构造函数循环依赖是无法解决的,只能报错

getBean -> doGetBean -> createBean ->doCreateBean

在createBean的时候doCreateBean实例化bean方法执行之前,验证singletonsCurrentlyInCreation这个集合中是否已经存在已经初始化的自己,有的话就直接报错了,

5 多例

getBean -> doGetBean -> createBean ->doCreateBean

多例的话,直接去掉了在createBean之前的单例验证部分代码,不从singletonObjects中取值,没一次都是重新去创建.

5.1 属性循环依赖

同单例的逻辑相同

5.2 构造函数循环依赖

getBean -> doGetBean -> createBean ->doCreateBean

在doGetBean方法中

if (isPrototypeCurrentlyInCreation(beanName)) {
   throw new BeanCurrentlyInCreationException(beanName);
}

利用了ThreadLocal定义了prototypesCurrentlyInCreation属性,然后线程里面的方法如果在执行getBean的话发现自己bean实例化过,就会报错。

如果没有正常的话,创建bean结束后会把这个beanName从ThreadLocal中移除

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值