GVKun编程网logo

Spring IOC源码笔记-SpringBean的实例化(spring的ioc源码解析)

24

本文将为您提供关于SpringIOC源码笔记-SpringBean的实例化的详细介绍,我们还将为您解释spring的ioc源码解析的相关知识,同时,我们还将为您提供关于1.spring5源码系列--S

本文将为您提供关于Spring IOC源码笔记-SpringBean的实例化的详细介绍,我们还将为您解释spring的ioc源码解析的相关知识,同时,我们还将为您提供关于1. spring5源码系列 -- Spring整体脉络 IOC加载过程 Bean的生命周期、2014-03-09 Spring的学习(1)------Spring管理Bean(实例化Bean)、3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析、3.4 spring5源码系列--循环依赖的设计思想 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终的实用信息。

本文目录一览:

Spring IOC源码笔记-SpringBean的实例化(spring的ioc源码解析)

Spring IOC源码笔记-SpringBean的实例化(spring的ioc源码解析)

Spring Bean的实例化

Bean的实例化顾名思义就是创建bean,然后被spring ioc容器纳入管理,然后在应用范围内可以获取bean,

在前面的章节中介绍了BeanDefinition的加载与注册,那么bean的实例化步骤是建立在BeanDefinition的加载与注册之上,

Bean的实例化包括创建所需的bean实例以及根据需要同时实例化bean所依赖的bean实例。

还记得在介绍beanFactory核心组件时有介绍BeanFactory的getBean方法

<T> T getBean(String name, Class<T> requiredType) throws BeansException;

该方法就是根据配置的bean的name以及bean的Class类型获取所需的bean对象,该方法就是我们探讨bean实例化的入口

BeanFactory实例化bean的时序图如下:

AbstractBeanFactory.java

protected <T> T doGetBean(
      final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      throws BeansException {

   final String beanName = transformedBeanName(name);
   Object bean;

   // 直接尝试从缓存中获取或者singletonFactories中的ObjectFactory中获取
   // 为什么会有这段代码,因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖时为了避免循环依赖
   // spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光,也就是将ObjectFactory加入到缓存中,一旦下一个bean创建的时候需要依赖上一个bean则直接使用ObjectFactory
  
   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 + "''");
         }
      }
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      // 判断当前的bean当前是否处于创建状态*(在当前线程中),避免重复创建,一般用于解决循环依赖
      // 只有在单例的情况下才会尝试解决循环依赖,原型模式下,如果存在 A,B互相依赖的时候,就会产生A还未创建完成的时候,因为对B的创建再次返回创建A,造成循环依赖,这是不允许的
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // 检查当前的beanfactory是否存在父beanfactory 若存在则从父beanfactory获取实例
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         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标记为已创建(或即将创建)。允许bean工厂优化其缓存以重复创建指定的bean
      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      try {
         //将GenericBeanDefinition合并为RootBeanDefinition
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

         //检查RootBeanDefinition是否是抽象的,如果是抽象将无法实例化
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         String[] dependsOn = mbd.getDependsOn();

         //确保当前bean所依赖的bean的先被初始化
         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 + "''");
               }
               //为给定的bean注册一个依赖bean,在销毁给定的bean之前销毁
               registerDependentBean(dep, beanName);
               try {
                 //获取并实例化依赖的bean
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "''" + beanName + "'' depends on missing bean ''" + dep + "''", ex);
               }
            }
         }

         // 创建bean的实例对象.
         // 如果bean的scope为"singleton"或者为""(也就是未指定scope的时候)创建单实例的bean
         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实例的对象,如果是FactoryBean,要么是bean实例本身,要么是它创建的对象
            // 因为在这一步的时候只是获得bean的最原始状态,并不一定是用户最终需要的bean,为什么呢,这里会考虑factoryBean,如果得到的bean是一个factoryBean
            // 则会最终调用factoryBean的getObject获得最终的bean
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }
         //创建Prototype作用域的bean
         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);
         }
        //创建Prototype作用域的bean
         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, new ObjectFactory<Object>() {
                  @Override
                  public Object getObject() throws BeansException {
                     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;
      }
   }

   // 检查所需类型是否与实际bean实例的类型匹配.
   if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
      try {
         return getTypeConverter().convertIfNecessary(bean, requiredType);
      }
      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());
      }
   }
    //返回所需要的bean
   return (T) bean;
}

单例bean的创建

DefaultSingletonBeanRegistry.java

Assert.notNull(beanName, "''beanName'' must not be null");
synchronized (this.singletonObjects) {
   //获取缓存的单例bean
   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 + "''");
      }
      //单例创建之前的回调。默认实现将singleton注册为当前正在创建的
      beforeSingletonCreation(beanName);
      //新创建单例的标识
      boolean newSingleton = false;
      boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
      if (recordSuppressedExceptions) {
         this.suppressedExceptions = new LinkedHashSet<Exception>();
      }
      try {
         //通过单例工厂创建bean
         singletonObject = singletonFactory.getObject();
         //将新创建单例的标识设为true
         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;
         }
         //单例创建后的回调。默认实现将singleton标记为不在创建中
         afterSingletonCreation(beanName);
      }
      if (newSingleton) {
         //将给定的单例对象添加到此工厂的单例缓存中。
         addSingleton(beanName, singletonObject);
      }
   }
   return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

单例对象的创建是通过ObjectFactory对象工厂来创建的,这是一个接口

T getObject() throws BeansException;

所以在AbstractBeanFactory.java中标红部分有一个ObjectFactory的匿名内部类的实现

sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
   @Override
   public Object getObject() throws BeansException {
      try {
         return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
         destroySingleton(beanName);
         throw ex;
      }
   }
});

该匿名内部类创建对象的行为实际则调用了createBean(beanName, mbd, args);方法,此方法在AbstractBeanFactory中是一个抽象方法,具体实现是在AbstractAutowireCapableBeanFactory中

AbstractAutowireCapableBeanFactory.java

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean ''" + beanName + "''");
   }
   RootBeanDefinition mbdToUse = mbd;

   // 确保此时bean类实际上已经解析,并从Beandefinition中取得解析的Class对象.
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // 让beanpostprocessor有机会返回代理而不是目标bean实例.
      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);
   }
   // 根据BeanDefinition创建bean实例  
   Object beanInstance = doCreateBean(beanName, mbdToUse, args);
   if (logger.isDebugEnabled()) {
      logger.debug("Finished creating instance of bean ''" + beanName + "''");
   }
   return beanInstance;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
      throws BeanCreationException {

   // bean实例的包装类.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      //创建bean的实例
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
    //获取bean的接口
   final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    //获取bean的类型
   Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
   //定义要实例化的目标类型
   mbd.resolvedTargetType = beanType;

   // 允许后处理(post-processors)程序修改合并的bean定义
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   //创建bean的时候,用来解决循环依赖,A -> b ,B->A
   // 每个单例对象在创建的时候首先会加入到正在创建缓存中singletonsCurrentlyInCreation中
   // 并且会在bean的属性填充之前 暴露一个ObjectFactory到singletonFactories<beanName,ObjectFactory>
   // 当检测到时循环引用的时候会通过之前暴露的ObjectFactory获取前期实例化好的并且是依赖的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");
      }
      addSingletonFactory(beanName, new ObjectFactory<Object>() {
         @Override
         public Object getObject() throws BeansException {
            return getEarlyBeanReference(beanName, mbd, bean);
         }
      });
   }

   // 初始化bean的实例
   // 并定义一个向外暴露的bean.
   Object exposedObject = bean;
   try {
      //填充bean的属性以及属性依赖的对象,依赖的属性对象将会通过getBean(name同样的逻辑)实例化,然后将依赖的对象填充到当前的bean的属性中
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) {
         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);
      }
   }
    //如果是循环引用
   if (earlySingletonExposure) {
      //通过之前暴露的singletonFactories<beanName,ObjectFactory> 跟据beanName获取对应的ObjectFactory
      // 通过ObjectFactory获取早期依赖的对象
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name ''" + beanName + "'' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "''getBeanNamesOfType'' with the ''allowEagerInit'' flag turned off, for example.");
            }
         }
      }
   }

   // 将bean注册为一次性的.
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

createBeanInstance的逻辑,并返回bean的包装类BeanWrapper

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
   // Make sure bean class is actually resolved at this point.
   Class<?> beanClass = resolveBeanClass(mbd, beanName);

   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn''t public, and non-public access not allowed: " + beanClass.getName());
   }

   if (mbd.getFactoryMethodName() != null)  {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

   // Shortcut when re-creating the same bean...
   boolean resolved = false;
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
   if (resolved) {
      if (autowireNecessary) {
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
         return instantiateBean(beanName, mbd);
      }
   }

   // Need to determine the constructor...
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      return autowireConstructor(beanName, mbd, ctors, args);
   }

   // 无需特殊处理:只需使用无参数构造函数反射实例化bean对象
   return instantiateBean(beanName, mbd);
}
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
   try {
      Object beanInstance;
      final BeanFactory parent = this;
      if (System.getSecurityManager() != null) {
         beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
               return getInstantiationStrategy().instantiate(mbd, beanName, parent);
            }
         }, getAccessControlContext());
      }
      else {
         //获取实例化策略,来对原生的bean进行实例化,最终会调用SimpleInstantiationStrategy的instantiate方法
         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      }
      //将原始bean的实例对象包装成BeanWrapperImpl实例
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      //对包装类进行初始化
      initBeanWrapper(bw);
      return bw;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
   }
}

SimpleInstantiationStrategy.java

public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
   // Don''t override the class with CGLIB if no overrides.
   if (bd.getMethodOverrides().isEmpty()) {
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse == null) {
            final Class<?> clazz = bd.getBeanClass();
            if (clazz.isInterface()) {
               throw new BeanInstantiationException(clazz, "Specified class is an interface");
            }
            try {
               if (System.getSecurityManager() != null) {
                  constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                     @Override
                     public Constructor<?> run() throws Exception {
                        return clazz.getDeclaredConstructor((Class[]) null);
                     }
                  });
               }
               else {
                  //反射获取bean的无参数构造器
                  constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
               }
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Throwable ex) {
               throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            }
         }
      }
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else {
      // Must generate CGLIB subclass.
      return instantiateWithMethodInjection(bd, beanName, owner);
   }
}

BeanUtils.java

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
   Assert.notNull(ctor, "Constructor must not be null");
   try {
      反射创建bean的实例
      ReflectionUtils.makeAccessible(ctor);
      return ctor.newInstance(args);
   }
   catch (InstantiationException ex) {
      throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
   }
   catch (IllegalAccessException ex) {
      throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
   }
   catch (IllegalArgumentException ex) {
      throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
   }
   catch (InvocationTargetException ex) {
      throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
   }
}

bean的填充逻辑

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
   PropertyValues pvs = mbd.getPropertyValues();

   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // Skip property population phase for null instance.
         return;
      }
   }

   //让任何instantiationawarebeanpostprocessor有机会在设置属性之前修改bean的状态。
   boolean continueWithPropertyPopulation = true;

   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }

   if (!continueWithPropertyPopulation) {
      return;
   }
   
   //如果bean配置了自动装配 byName或ByType则进行自动装配属性
   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

      // Add property values based on autowire by name if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }

      // Add property values based on autowire by type if applicable.
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }

      pvs = newPvs;
   }

   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

   if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
                  return;
               }
            }
         }
      }
      if (needsDepCheck) {
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   }

   //申请并设置bean的属性值
   applyPropertyValues(beanName, mbd, bw, pvs);
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
   //如果bean没有任何属性值则填充结束
   if (pvs == null || pvs.isEmpty()) {
      return;
   }

   if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
      ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
   }

   MutablePropertyValues mpvs = null;
   List<PropertyValue> original;

   if (pvs instanceof MutablePropertyValues) {
      mpvs = (MutablePropertyValues) pvs;
      if (mpvs.isConverted()) {
         // Shortcut: use the pre-converted values as-is.
         try {
            bw.setPropertyValues(mpvs);
            return;
         }
         catch (BeansException ex) {
            throw new BeanCreationException(
                  mbd.getResourceDescription(), beanName, "Error setting property values", ex);
         }
      }
      original = mpvs.getPropertyValueList();
   }
   else {
      original = Arrays.asList(pvs.getPropertyValues());
   }

   TypeConverter converter = getCustomTypeConverter();
   if (converter == null) {
      converter = bw;
   }
   BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

   // Create a deep copy, resolving any references for values.
   List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
   boolean resolveNecessary = false;
   for (PropertyValue pv : original) {
      if (pv.isConverted()) {
         deepCopy.add(pv);
      }
      else {
         //提取属性名
         String propertyName = pv.getName();
         //属性值对象
         Object originalValue = pv.getValue();
         //在必要时解析对工厂中其他bean的任何引用。
         Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
         Object convertedValue = resolvedValue;
         boolean convertible = bw.isWritableProperty(propertyName) &&
               !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
         if (convertible) {
            //转换在配置文件中的各种属性值到map、list、properties的转换,并将转换后的值填充到bean的属性当中
            convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
         }
         //可能在合并的bean定义中存储转换后的值,以避免对每个创建的bean实例进行重新转换.
         if (resolvedValue == originalValue) {
            if (convertible) {
               pv.setConvertedValue(convertedValue);
            }
            deepCopy.add(pv);
         }
         else if (convertible && originalValue instanceof TypedStringValue &&
               !((TypedStringValue) originalValue).isDynamic() &&
               !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
            pv.setConvertedValue(convertedValue);
            deepCopy.add(pv);
         }
         else {
            resolveNecessary = true;
            deepCopy.add(new PropertyValue(pv, convertedValue));
         }
      }
   }
   if (mpvs != null && !resolveNecessary) {
      mpvs.setConverted();
   }

   // Set our (possibly massaged) deep copy.
   try {
      bw.setPropertyValues(new MutablePropertyValues(deepCopy));
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
   }
}

BeanDefinitionValueResolver.java

public Object resolveValueIfNecessary(Object argName, Object value) {
   //如果依赖的属性是一个运行时的引用,则解析引用类型
   if (value instanceof RuntimeBeanReference) {
      RuntimeBeanReference ref = (RuntimeBeanReference) value;
      return resolveReference(argName, ref);
   }
   else if (value instanceof RuntimeBeanNameReference) {
      String refName = ((RuntimeBeanNameReference) value).getBeanName();
      refName = String.valueOf(doEvaluate(refName));
      if (!this.beanFactory.containsBean(refName)) {
         throw new BeanDefinitionStoreException(
               "Invalid bean name ''" + refName + "'' in bean reference for " + argName);
      }
      return refName;
   }
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
   try {
      String refName = ref.getBeanName();
      refName = String.valueOf(doEvaluate(refName));
      if (ref.isToParent()) {
         if (this.beanFactory.getParentBeanFactory() == null) {
            throw new BeanCreationException(
                  this.beanDefinition.getResourceDescription(), this.beanName,
                  "Can''t resolve reference to bean ''" + refName +
                  "'' in parent factory: no parent factory available");
         }
         return this.beanFactory.getParentBeanFactory().getBean(refName);
      }
      else {
         //如果依赖的属性是一个引用,则根据引用的属性名称创建依赖的bean并注册依赖的bean
         Object bean = this.beanFactory.getBean(refName);
         this.beanFactory.registerDependentBean(refName, this.beanName);
         return bean;
      }
   }
   catch (BeansException ex) {
      throw new BeanCreationException(
            this.beanDefinition.getResourceDescription(), this.beanName,
            "Cannot resolve reference to bean ''" + ref.getBeanName() + "'' while setting " + argName, ex);
   }
}

Bean的循环依赖解决方式

循环依赖解决方式的原则

1: 如果bean的依赖是通过构造器注入,则拒绝解决

     其原理如下:

         原型模式下,如果存在 ServiceA -> ServiceB,ServiceB -> ServiceA互相依赖的时候,在创建ServiceA的时候首先会将ServiceA添加到Set<String> singletonsCurrentlyInCreation中,检测到依赖ServiceB然后实例化ServiceB

         并将ServiceB添加到Set<String> singletonsCurrentlyInCreation,同时检测到依赖的ServiceA,然后再一次实例化ServiceA,当检测到ServiceA已经存在singletonsCurrentlyInCreation之中,则会抛出异常BeanCurrentlyInCreationException

         根据异常栈信息可以看到如下信息:

             Error creating bean with name ''ServiceB'': Requested bean is currently in creation: Is there an unresolvable circular reference?

            翻译: 创建名为''ServiceB''的bean时出错:请求的bean(ServiceA)当前正在创建中:是否存在无法解析的循环引用?

     具体代码在DefaultSingletonBeanRegistry.java中

   

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(beanName, "''beanName'' must not be null");
   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;
         ......
}
protected void beforeSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}

2 : 如果bean的依赖是通过Setter注入,则解决方式如下:

   第一步:

             首先获取ServiceA的时候从singletonObjects或者earlySingletonObjects或者singletonFactories中的ObjectFactory获取单例

             由于第一步,singletonObjects中没有ServiceA的缓存,当前的singletonsCurrentlyInCreation还没有该ServiceA,故不满足条件

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   //从bean工厂的单例缓存中获取
   Object singletonObject = this.singletonObjects.get(beanName);
   //如果缓存没有的时候再判断当前的bean是否处在创建之中
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         //从earlySingletonObjects缓存中获取ObjectFactory
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
            //从bean对应的ObjectFactory缓存中获取ObjectFactory
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               //从ObjectFactory中获取
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

 第二步:

        实例化ServiceA,在实例化之前同样需要执行beforeSingletonCreation(beanName)逻辑,将ServiceA放在当前创建缓存中singletonsCurrentlyInCreation

        然后实例化ServiceA,调用无参数的构造器获得原始的ServiceA的实例,然后将ServiceA添加到singletonFactories

       

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
   .....
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      addSingletonFactory(beanName, new ObjectFactory<Object>() {
         @Override
         public Object getObject() throws BeansException {
            return getEarlyBeanReference(beanName, mbd, bean);
         }
      });
   }

   

   return exposedObject;
}

第三步骤:

  填充ServiceA,发现有一个RuntimeBeanReference的引用ServiceB,然后解析引用ServiceB,然后执行getBean("serviceB"),这一步有走到了实例化ServiceB的逻辑

  由于ServiceB也是首次实例化,执行的逻辑与ServiceA相同,将ServiceB置于singletonsCurrentlyInCreation之中,同时将实例化ServiceB,调用无参数的构造器获得原始的ServiceB的实例,然后将ServiceB添加到singletonFactories

  再继续执行,发现有一个RuntimeBeanReference的引用ServiceA的引用,然后又执行getBean("serviceA"),的逻辑,这一次又会走到protected Object getSingleton(String beanName, boolean allowEarlyReference)方法

  只不过走到这一步的时候与第一次实例化ServiceA不同,已经发生了微妙的变化,由于最开始的时候ServiceA的实例已经过构造器反射实例化,同时最开始的时候singletonsCurrentlyInCreation已经包含ServiceA,同时singletonFactories中也包含了ServiceA的ObjectFactory

 所以这一步将直接根据ServiceA的ObjectFactory暴露出ServiceA实例,然后将ServiceA注入到ServiceB

第四步:

 由第三步可知,serviceB的实例已经初始成功,那么最后ServiceA再回到装配ServiceB的时候 ,同样ServiceB也已经处于singletonsCurrentlyInCreation,且singletonFactories中也包含了ServiceB的ObjectFactoryB

 那么装配ServiceA的逻辑也是如此

附录:

  构造器的循环依赖并不能像解决Setter那样,因为构造器注入的时候,在反射创建原对象时,发现构造器参数有依赖的bean,于是通过ConstructorResolver解析器解析构造其参数RuntimeBeanReference ,然后通过new BeanDefinitionValueResolver,

  发现依赖直接通过   getBean("referenceName")立刻实例化依赖的对象,并不能像setter那样,调用无参数的构造器实例化

  然后提前暴露一个ObjectFactory到singletonFactories中,所以当发现依赖的对象处于singletonsCurrentlyInCreation中时,抛出异常

1. spring5源码系列 -- Spring整体脉络 IOC加载过程 Bean的生命周期

1. spring5源码系列 -- Spring整体脉络 IOC加载过程 Bean的生命周期

 

目录

1. spring整体脉络

2 描述beanfactory

3. beanfactory和ApplicationContext的区别

4. 简述SpringIoC的加载过程

5. 简述Bean的生命周期

6. Spring中有哪些扩展接口及调用机制

 

一. spring源码整体脉络介绍及源码编译

 1.1. 什么是IOC

ioc是控制反转,这是一种设计理念,用来解决的是层和层之间,类和类之间的耦合问题.

比如,现在有A,B两个类,在A类中引用了B类. 那么如果有一天,B类要被替换掉,我们会怎么办呢?如果B类被引用了100次,我们要替换100次?

现在呢,A是直接调用B,如果我们间接的调用B,将B包装起来,如果以后将B换成C,只需要在包装类里面替换就可以了. 我们不需要修改A类. 这就是控制反转.

 

Spring使用了ioc,Spring.ioc(A,B) 将A和B的引用都存在ioc中,spring会帮我们维护好,完全不用担心.

当我们在A中要使用B的时候,使用B对应的接口,然后使用@Autowired注解

A {
   @Autowired
   private IB b;  
}

什么时候把B换掉了,不痛不痒的,只需要把新的类放到IoC中就可以了.

1.2. Spring源码的整体脉络梳理

Spring IoC是一个容器,在Spring Ioc中维护了许多Bean

那这些bean是如何被注册到IoC中的呢? 换句话说,我们自定义的类,是如何作为一个bean交给IoC容器去管理的呢?

先来回忆,我们在开发spring的时候的步骤: 

第一步: 配置类. 配置类可以使用的方式通常由
      1) xml配置
      2) 注解配置
      3) javaconfig方式配置
第二步: 加载spring上下文
      1) 如果是xml,则new ClasspathXmlApplicationContext("xml");
      2) 如果是注解配置: 则new AnnotationConfigApplicationContext(config.class)

第三步: getBean() 
我们会讲自定义的类,通过xml或者注解的方式注入到ioc容器中.

在这一步,会将xml或注解中指定的类注入到IoC容器中. 

1.2.1 那么,到底是如何将一个类注入到ioc中的呢? 

下面就来梳理一下整个过程. 

第一问: 一个类要生产成一个Bean,最重要最核心的类是什么?

是beanfactory

 

第二问: beanfactory是什么呢?

beanfactory是Spring顶层的核心接口--使用了简单工厂模式. 通常都是根据一个名字生产一个实例,根据传入的唯一的标志来获得bean对象,但具体是穿入参数后创建,还是穿入参数前创建,这个要根据 具体情况而定,根据名字或类型生产不同的bean. 

一句话总结: beanfactory的责任就是生产Bean

来看下面这段代码: 

public static void main( String[] args ) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.getBean("***");
    }

这段代码实现的功能是,读取当前文件所在目录及其子目录中的文件,然后获取指定名称的bean,整个流程如下图所示: 

 

首先,通过ClasspathXmlApplicationContext或者AnnotationConfigApplicationContext去读取配置,然后将其交给beanfactory.

第三. beanfactory调用getBean()方法,将Bean注入到IoC容器中

我们发现,配置的读取,可能是xml方式,也可能是annotation的方式, 不同的方式读取应该使用的是不同的工具. 那么这些工具读取的结果应该是统一的,然后才能交给beanfactory去处理.

因为在beanfactory中是不会对这些异同点进行处理的. beanfactory的作用只有一个,就是个生产Bean

1.2.2 那么,不同的工具读取配置是如何统一的呢?

我们知道,读取配置这一块,应该会有一个不同的实现. 将xml和注解方式读取成统一的东西,放入到beanfactory中. 这个东西是谁呢?就是BeanDeFinition(Bean定义) 

什么意思呢? 如下图:

 

 看绿色框框住的部分. 这个含义是: 通过不同的工具,可能是xmlApplicationContext,可能是annotationApplicationContext工具 读取的配置,最后都会构造成BeanDeFinition对象. 然后将BeanDeFinition传递给beanfactory,beanfactory统一处理BeanDeFinition对象,调用getBean()方法,将其放入IoC容器中.

 

1.2.3 那么又是是如何读取配置统一构造成BeanDeFinition的呢?

我们来举个例子,现在有一个人,比如说我刚买了一个房子,我要装修. 需要一个衣柜,这时候,我会找到一个衣柜店. 然后告诉他我的需求,柜子的颜色,款式格式什么样. 然后衣柜店记录我的需求,这个时候,他不会自己生产,他会通知工厂,让工厂来生产. 工厂按照什么生产呢,衣柜店有一个设计师, 他们的设计师. 会按照我的需求设计出一张图纸. 然后将图纸交给工厂. 工厂按照图纸要求生产Bean. 

整个过程如下图:

 

 

 入口是"我"

1. 我有一个需求,打一个柜子,找到衣柜店

2. 我告诉衣柜店我的需求,款式,然后衣柜店的设计师按照我的要求,设计出一张图纸

3. 衣柜店将图纸给到工厂,工厂按照图纸生产柜子

这是制造衣柜的过程. 其中在画图纸的时候,画一张就给工厂给一张,这样效率太低了. 我们可以画了n张,一起给工厂. 所以,在设计图纸这块是一个容器,存放多张图纸

 

后面,如果我还想定制一个橱柜店. 那么,就告诉设计师我的橱柜的颜色,就可以了. 流程和上面都是一样的. 

 

 

整个这个过程,就类似于我们的bean生产的过程

 

1. 定义了一个带有@Component注解的类,我找到衣柜店,衣柜店就类似于ApplicationContext.

2. 我告诉ApplicationContext我的需求,我要懒加载@Lazy,设置单例模式还是多例模式@Scope. 对应的就是定制柜子的颜色,款式. 然后衣柜店里的设计师BeanDeFinitionRegistry根据我的需求设计出图纸,也就是构造成BeanDeFinition. 不同的BeanDeFinitionRegistry设计出不同的BeanDeFinition,然后将他们都放在容器中.

3. 衣柜店ApplicationContext统一将一摞图纸BeanDeFinitionMap交给工厂,  然后工厂按照要求生产Bean,然后将生成的bean放入到IoC容器中.

 

这是一个带有@Component的类被加载的过程. 

 

衣柜店要要想生意好,那么他要去拉活呀,所以还需要好的销售. 销售要去扫楼盘,去联系,哪些人有装修的需求. 挨个询问. 

可是问了100个人,可能只有10个人有装修的需求. 于是还要有一个接待,这个接待要联系客户,看看哪些是有意向的客户,将其筛选出来. 然后定制家具.

这里多了两类人: 销售和接待. 具体工作如下.

 

销售就相当于我们的BeanDeFinitionReader,他的作用是去扫楼盘,找到潜在客户. 对应的就是BeanDeFinitionReader去读取xml配置或者Annotation注解. 

xml中的配置有很多,注解也有很多,并不都是我们的目标. 于是有了接待

接待要去扫描所有潜在客户. 将有意向的客户扫描出来. 这就类似于我们的BeanDeFinitionScanner,去扫描潜在客户,最后将带有@Component注解的类筛选出来

这就是后面需要定制家具的客户了

BeanDeFinitionReader对应的就去读取配置类,看看有哪些需求需要搞装修.


它本身也是一个抽象类,可以看到他有AnnotationBeanDeFinitionReader和XmlBeanDeFinitionReader


我们配置了配置包,去扫描这个包下所有的类,然后将扫描到的所有的类交给BeanDeFinitionScanner,它会去过滤带有@Component的类. 

在和上面的流程连接起来,就是整个配置文件被加载到IoC的过程了. 

 

1.3. ApplicationContext和factorybean的区别

1. factorybean的功能就是生产bean. 他生产bean是根据BeanDeFinition来生产的. 所以,一次只能生产一个

2. ApplicationContext有两种. 一种是xmlApplicationContext,另一种是annotationApplicationContext,他传入的参数是一个配置文件. 也就是可以加载某个目录下所有带有@Component的类

他们两个都各有使用场景. 使用ApplicationContext的居多.

 

另一个区别: 就是后面会说到的,ApplicationContext有两个扩展接口,可以用来和外部集成. 比如和MyBatis集成.

 

 

 

 

1.4. Bean的生命周期

 

 

如上图,beanfactory拿到BeanDeFinition,直接调用getBean()就生产Bean了么? 

不是的,生产Bean是有一个流程的. 下面我们来看看Bean的生命周期

 

第一步: 实例化. bean实例化的时候从BeanDeFinition中得到Bean的名字,然后通过反射机制,将Bean实例化. 实例化以后,这是还只是个壳子,里面什么都没有.

第二步: 填充属性. 经过初始化以后,bean的壳子就有了,bean里面有哪些属性呢? 在这一步填充


第三步: 初始化. 初始化的时候,会调用initMethod()初始化方法,destory()初始化结束方法

这个时候,类就被构造好了.

第四步: 构造好了的类,会被放到IoC的一个Map中. Map的key是beanName,value是bean实例. 这个Map是一个单例池,也就是我们说的一级缓存


第五步: 我们就可以通过getBean("user"),从单例池中获取雷鸣是user的类了.

 

 在构造bean的过程中,还会有很多细节的问题,比如循环依赖.

 

 

 A类里面调用了B类,所以beanfactory在构造A的时候,会去构造B. 然后在构造B的时候,发现,B还依赖了A. 这样,就是循环依赖. 这是不可以的. 

Spring是如何解决循环依赖的问题的呢? 

设置出口. 比如A在构造的过程中,那么设置一个标记,正在构造中. 然后构造B,B在构造的过程中应用了A,有趣构造A,然后发现A正在构造中,那么,就不会再次构造A了. 

后面还会详细讲解Spring是如何解决循环引用的. 这里我们需要知道的是: Spring使用的是三级缓存来解决循环引用的问题

 其实,bean是存在一级缓存里面,循环引用使用的是三级缓存来解决的. 其实,一、二、三级缓存就是Map。

 

1.5. Spring中的扩展接口

有两个非常重要的扩展接口. beanfactoryPostProcessor(Bean工厂的后置处理器) 和 BeanDeFinitionRegistryPostProcessor

这两个接口是干什么的呢? 

我们在这个图里面,看到了设计师要设计出图纸,然后把图纸交给工厂去生产. 那么设计师设计出来的图纸,有没有可能被修改呢?

当然是可以被修改的. 只要还没有交给工厂,就可以修改.

beanfactoryPostProcessor(Bean工厂的后置处理器)的作用就是修改BeanDeFinition.

1. beanfactoryPostProcessor: 修改BeanDeFinition.

是一个接口,我们的类可以实现这个接口,然后重写里面的方法

public class DefinedPost implements beanfactoryPostProcessor {

    /**
     * 重写Bean工厂的后置处理器
     * @param beanfactory
     * @throws BeansException
     */
    @Override
    public void postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) throws BeansException {
        // beanfactory 拿到工厂了,就可以获取某一个Bean定义了
        GenericBeanDeFinition car = (GenericBeanDeFinition) beanfactory.getBeanDeFinition("Car");
        // 拿到了car,然后修改了Car的类名为com.example.tulingcourse.Tank. 那么后面在获取的Bean里面,将其转换为Car,就会报错了
        car.setBeanClassName("com.example.tulingcourse.Tank");
    }
}

第一步: 实现了beanfactoryPostProcessor接口,然后需要重写里面的方法

第二步: 我们发现重写方法直接给我们了beanfactory,bean工厂

第三步: 拿到bean工厂,我们就可以根据名称获取BeanDeFinition,也就是bean定义了. 

第四步: 我们修改了bean定义中的类名为Tank. 

 

这时候会发生什么呢? 从bean工厂中构建的car,取出来以后转换成Car对象,会报错,

public static void main(String[] args) {
    

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
    
        Car car = context.getBean("car",Car.class); // 这里会报错,因为已经被修改
        System.out.println(car.getName());
    }

 

执行流程: 当spring启动的时候,就会去执行AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TulingCourseApplication.class);

然后ApplicationContext回去扫描所有实现了beanfactoryPostProcessor对象的类,然后执行postProcessbeanfactory方法. 

 

beanfactoryPostProcessor被使用到的场景非常多,在集成其他组件的时候,比如集成mybatis

 

2. BeanDeFinitionRegistryPostProcessor 注册BeanDeFinition

这是一个Bean定义注册的后置处理器.BeanDeFinitionRegistryPostProcessor本事是实现了beanfactoryPostProcessor 接口

 

 我们来看个demo

public class DefinedPost implements BeanDeFinitionRegistryPostProcessor {

    /**
     * 重写Bean工厂的后置处理器
     * @param beanfactory
     * @throws BeansException
     */
    @Override
    public void postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) throws BeansException {
        // beanfactory 拿到工厂了,就可以获取某一个Bean定义了
        GenericBeanDeFinition car = (GenericBeanDeFinition) beanfactory.getBeanDeFinition("Car");
        // 拿到了car,就会报错了
        car.setBeanClassName("com.example.tulingcourse.Tank");
    }

    @Override
    public void postProcessBeanDeFinitionRegistry(BeanDeFinitionRegistry beanDeFinitionRegistry) throws BeansException {

    }
}

一个类实现了BeanDeFinitionRegistryPostProcessor,需要重写postProcessBeanDeFinitionRegistry方法,这个方法直接将BeanDeFinitionRegistry就给我们了. 

然后使用beanDeFinitionRegistry.registerBeanDeFinition(); 就可以添加图纸了

在这里可以注册新的bean,也可以删除注册的bean. 多注册一个,bean工厂就要多构建一个. 

 

总结:

    beanfactoryPostProcessor和BeanDeFinitionRegistryPostProcessor这两个扩展类是很重要的类, 这对于向外部扩展起到了很大的的作用,比如: 集成mybatis

beanfactoryPostProcessor和BeanDeFinitionRegistryPostProcessor是在ApplicationContext中的两个扩展接口. 这也是ApplicationContext和beanfactory的区别之一,因为有了这两个扩展节点,就可以和外部做集成. 比如Mybatis集成.  比如: 扫描配置类,就是通过 这两个扩展点的方式实现的.

 

这个扩展点的作用:

1. 除了IoC,其他的扩展,比如AOP,和MyBatis集成,都要用到这两个扩展点. 之所以Spring能够有序不乱的和很多外部组件整合,都是这两个扩展点的功能

 

1.6 Bean的扩展点

除了ApplicationContext有扩展点,  在Spring IoC中的bean也有扩展点. BeanPostProcessor(Bean的后置处理器). 如果使用在getBean()之前,那么可以阻止构建Bean,还可以自定义构建Bean.

 

BeanPostProcessor使用的场景有很多. 在Bean实例化之前和之后会被调用.  在填充属性之前和之后也会被调用,初始化之前和之后也会调用. 有些过程不只调用一次. 整个过程一共会调用9次. 在每一个过程都可以扩展Bean.

 

思考: Spring加入AOP是如何实现呢?

集成AOP肯定不会和IoC糅合在一块了. AOP就是通过BeanPostProcessor(Bean后置处理器)整合进来的.

AOP的实现方式有两种: 一种是cglib,另一种是JDK. 

假如说要进行集成,会在那个步骤继承呢? 比如要加日志,使用AOP的方式加. 我们通常是在初始化之后加AOP. 在这里将AOP集成进来.

 

如上图: 当面试的时候面试官问你,Bean的生命周期,我们不能只说实例化-->填充属性-->初始化. 还需要说初始化的时候,还有一些列的aware.

1.7. Spring IOC的加载过程

 

 

对照上图,我们来简述ioc的加载过程 

我们将一个类加载成Bean,不是一步到位的,需要经历一下的过程. 

1. 首先,我们要将类加载成BeanDeFinition(Bean定义)

  加载成bean定义,有以下几个步骤:

  1) 使用BeanDeFinitionReader加载配置类,此时是扫描所有的xml文件或者项目中的注解. 这里面有些使我们的目标类,有些不是

  2) 使用BeanDeFinitionScanner扫描出我们的目标类. 

  3) 使用BeanDeFinitionRegistry注册bean到BeanDeFinitionMap中.

2. 然后,ApplicationContext可以调用beanfactoryPostProcessor修改bean定义,还可以调用BeanDeFinitionRegistryPostProcessor注册bean定义

3. 将BeanDeFinition交给beanfactory处理,beanfactory调用getBean()生成Bean或者调用Bean(getBean()有两个功能). 

4. 成产bean的时候,首先会实例化,然后填充属性(主要是读取@Autowire,@Value等注解). 在初始化Bean,这里会调用initMethod()方法和初始化销毁方法destroy(). 初始化的时候还会调用一堆的Aware,而且在bean生成的过程中 会有很多扩展点,供我们去扩展.

5. 将生产出的Bean放入到Map中,map是一个一级缓存池. 后面,我们可以通过getBean("user")从缓存池中获取bean

 

2014-03-09 Spring的学习(1)------Spring管理Bean(实例化Bean)

2014-03-09 Spring的学习(1)------Spring管理Bean(实例化Bean)

1.搭建与测试Spring的开发环境

 

      PS: Spring-beans-2.5.xsd  (为使在Beans.xml操作顺畅) Perferences--->MyEclipse--->Files and Editors---->XML--->XML Catalog--->add User Specified Entries

     

2.Spring管理Bean小试牛刀

    代码实现:

PersonServiceImpl.java

/**实现类**/
package cn.itcast.service.impl;

import cn.itcast.dao.PersonDao;
import cn.itcast.service.PersonService;

public class PersonServiceImpl implements PersonService {
	public void add(){
		System.out.println("This is a add()");
	}
}

   

Beans.xml位于类路径

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

       <!-- 构造器实例对象 !-->
       <bean id="personService"  scope="prototype"/>
</beans>

SpringTest.java测试类(用JUNIT框架测试)

package cn.itcast.test;


import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.itcast.dao.PersonDao;
import cn.itcast.mycontext.MyClassPathXmlApplicationContext;
import cn.itcast.service.PersonService;

public class SpringTest {
	@Test
	public void instaceBean() {
	   ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
	   PersonService serviceBean = (PersonService)context.getBean("personService");
	   serviceBean.add();
	}
}
//output:
This is a add()
//~

 PS:可以通过Spring Framework 开发参考手册或者自带API学习.

3.手动编码完成部分实例化Bean的工作

 

BeanDefinition.java 配置Beans.xml文件中相对应的元素

package cn.itcast.mycontext;
public class BeanDefinition {
	private String id;
	private String className;
	public BeanDefinition(String id, String clazz) {
		this.id=id;
		this.className = clazz;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
}

MyClassPathXmlApplicationContext.java 读取Beans.xml

package cn.itcast.mycontext;


import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;


public class MyClassPathXmlApplicationContext {
	private List<BeanDefinition> BeanDefinitions = new ArrayList<BeanDefinition>();
	/**Key:id   Value:instaceBean **/
	private Map<String,Object> sigletons = new HashMap<String,Object>();
	public MyClassPathXmlApplicationContext(String filename){
		this.readXml(filename);
		this.instaceBeans();
	}
	/**
	 * 实例化Bean
	 */
	private void instaceBeans() {
		for(BeanDefinition beanDefinition:BeanDefinitions){
			if(beanDefinition.getClassName()!=null && beanDefinition.getClassName().trim()!=""){
			  try {
				sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
			} catch (InstantiationException | IllegalAccessException
					| ClassNotFoundException e) {
				e.printStackTrace();
			}
			}
		}
	}

	/**
	 * 读取配置Bean的XML文件
	 * dom4j-1.6.1.jar,jaxen-1.1-beta-6.jar
	 * @param filename
	 */
	private void readXml(String filename) {
		SAXReader reader = new SAXReader();
		Document document = null;
		try{
			URL url = this.getClass().getClassLoader().getResource(filename);
			document = reader.read(url);
			Map<String,String> nsMap = new HashMap<String,String>();
			nsMap.put("ns","http://www.springframework.org/schema/beans");
			XPath xsub =  document.createXPath("//ns:beans/ns:bean");
			xsub.setNamespaceURIs(nsMap);
			@SuppressWarnings("unchecked")
			List<Element> elements = xsub.selectNodes(document);
			/**dom4j相关知识**/
			for(Element element : elements){
				String id = element.attributeValue("id");  //获取id元素对应值
				String clazz = element.attributeValue("class"); //获取class元素对应值
				BeanDefinition beanDfine = new BeanDefinition(id,clazz);
				BeanDefinitions.add(beanDfine);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 获取Bean实例
	 * @param beanName
	 * @return
	 */
	public Object getBean(String beanName){
		return this.sigletons.get(beanName);
	}
}

4.Spring的三种实例化Bean的方式

    

 4.1. 用构造器来实例化

当采用构造器来创建bean实例时,Spring对class并没有特殊的要求, 我们通常使用的class都适用。也就是说,被创建的类并不需要实现任何特定的  接口,或以特定的方式编码,只要指定bean的class属性即可。不过根据所采用 的IoC类型,class可能需要一个默认的空构造器。

此外,IoC容器不仅限于管理JavaBean,它可以管理任意  的类。不过大多数使用Spring的人喜欢使用实际的JavaBean(具有默认的(无参)构造器  及setter和getter方法),但在容器中使用非bean形式(non-bean style)的类也是可  以的。比如遗留系统中的连接池,很显然它与JavaBean规范不符,但Spring也能管理它。

当使用基于XML的元数据配置文件,可以这样来指定bean类:

<!-- id值特殊字符集不能使用  !-->
<bean id="exampleBean" /> 
<bean name="anotherExample" />
<bean id="personService"  scope="prototype"/>

给构造函数指定参数以及为bean实例设置属性将在随后的 部分中谈及。

4.2. 使用静态工厂方法实例化

当采用静态工厂方法创建bean时,除了需要指定class 属性外,还需要通过factory-method属性来指定创建bean实例  的工厂方法。Spring将调用此方法(其可选参数接下来介绍)返回实例对象,就此而言, 跟通过普通构造器创建类实例没什么两样。

下面的bean定义展示了如何通过工厂方法来创建bean实例。注意,此定义并 未指定返回对象的类型,仅指定该类包含的工厂方法。在此例中, createInstance()必须是一个static方法。

<bean id="exampleBean"   factory-method="createInstance"/>
 <bean id="personServiceFactory" 
              factory-method="getPersonServiceImpl"/>

给工厂方法指定参数以及为bean实例设置属性将在随后的部份中谈及。

4.3. 使用实例工厂方法实例化

与  使用静态工厂方法实例化类似,用来进行实例化的非静态实例工厂方法位 于另外一个bean中,容器将调用该bean的工厂方法来创建一个新的bean实例。为使  用此机制,class属性必须为空,而factory-bean  属性必须指定为当前(或其祖先)容器中包含工厂方法的bean的名称,而该 工厂bean的工厂方法本身必须通过factory-method属性来设定。

<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" >   
<!-- inject any dependencies required by this locator bean --> 
</bean> 
<!-- the bean to be created via the factory bean --> 
<bean id="exampleBean"  factory-bean="serviceLocator"   factory-method="createInstance"/>

<!-- MyDemo -->
 <bean id="personServiceFactory2" 
       />
 <bean id="personServiceFactory3" 
       factory-bean="personServiceFactory2"
       factory-method="getPersonServiceImpl2"/>

虽然设置bean属性  的机制仍然在这里被提及,但隐式的做法是由工厂bean自己来管理以及通过依 赖注入(DI)来进行配置。

5.Bean的作用域以及Bean更多知识

   参考:Spring framework 2.5文档第三章Ioc(控制反转)容器


3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析

3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析

根据之前解析的循环依赖的源码,分析了一级缓存,二级缓存,三级缓存的作用以及如何解决循环依赖的. 然而在多线程的情况下,Spring在创建bean的过程中,可能会读取到不完整的bean. 下面,我们就来研究两点:

1. 为什么会读取到不完整的bean.

2. 如何解决读取到不完整bean的问题.

 

和本文相关的spring循环依赖的前两篇博文如下: 

3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

3.2spring源码系列----循环依赖源码分析

一. 为什么会读取到不完整的bean.

我们知道,如果spring容器已经加载完了,那么肯定所有bean都是完整的了,但如果,spring没有加载完,在加载的过程中,构建bean就有可能出现不完整bean的情况

如下所示: 

首先,有一个线程要去创建A类,调用getBean(A),他会怎么做呢?

第一步: 调用getSingleton()方法,去缓存中取数据,我们发现缓存中啥都没有,肯定返回null. 

第二步: 将其放入到正在创建集合中,标记当前bean A正在创建

第三步: 实例化bean

第四步: 将bean放到三级缓存中. 定义一个函数接口,方便后面调用

addSingletonFactory(beanName,() -> getEarlyBeanReference(beanName,mbd,bean));

第四步: 属性赋值. 在属性赋值的时候,返现要加载类B,就在这个时候,另一个线程也进来了,要创建Bean A.

第五步: 线程2 创建bean,也是先去调用getSinglton()从缓存中取,一二级换粗中都没有,但是三级缓存中却是有的. 于是就调用动态代理,去创建bean,很显然这时候创建的bean是不完整的. 然后将其放入到二级缓存中,二级缓存里的bean也是不完整的. 这就导致了后面是用的bean可能都是不完整的. 详细的分析上图

 

二. 如何解决读取到不完整bean的问题.

其实,之所以出现这样的问题,原因就在于,第一个bean还没有被创建完,第二个bean就开始了. 这是典型的并发问题. 

针对这个问题,其实,我们加锁就可以了.  

 用自己手写的代码为例

第一: 将整个创建过程加一把锁

/**
     * 获取bean,根据beanName获取
     */
    public static Object getBean(String beanName) throws Exception {

        // 增加一个出口. 判断实体类是否已经被加载过了
        Object singleton = getSingleton(beanName);
        if (singleton != null) {
            return singleton;
        }
        Object instanceBean;
        synchronized (singletonObjects) {

             标记bean正在创建
            if (!singletonsCurrectlyInCreation.contains(beanName)) {
                singletonsCurrectlyInCreation.add(beanName);
            }

            *
             * 第一步: 实例化
             * 我们这里是模拟,采用反射的方式进行实例化. 调用的也是最简单的无参构造函数
             */
            RootBeanDeFinition beanDeFinition = (RootBeanDeFinition) beanDeFinitionMap.get(beanName);
            Class<?> beanClass = beanDeFinition.getBeanClass();
             调用无参的构造函数进行实例化
            instanceBean = beanClass.newInstance();


            *
             * 第二步: 放入到三级缓存
             * 每一次createBean都会将其放入到三级缓存中. getobject是一个钩子方法. 在这里不会被调用.
             * 什么时候被调用呢?
             * 在getSingleton()从三级缓存中取数据,调用创建动态代理的时候
             
            singletonFactories.put(beanName,new ObjectFactory() {
                @Override
                public Object getobject() throws BeansException {
                    return new JdkProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.(beanName),beanName);
                }
            });
            earlySingletonObjects.put(beanName,instanceBean);

            *
             *  第三步: 属性赋值
             *  instanceA这类类里面有一个属性,InstanceB. 所以,先拿到 instanceB,然后在判断属性头上有没有Autowired注解.
             *  注意: 这里我们只是判断有没有Autowired注解. spring中还会判断有没有@Resource注解. @Resource注解还有两种方式,一种是name,一种是type
             
            Field[] declaredFields = beanClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                 判断每一个属性是否有@Autowired注解
                Autowired annotation = declaredField.getAnnotation(Autowired.class);
                if (annotation != ) {
                     设置这个属性是可访问的
                    declaredField.setAccessible(true);
                     那么这个时候还要构建这个属性的bean.
                    
                     * 获取属性的名字
                     * 真实情况,spring这里会判断,是根据名字,还是类型,还是构造函数来获取类.
                     * 我们这里模拟,所以简单一些,直接根据名字获取.
                     
                    String name = declaredField.getName();

                    *
                     * 这样,在这里我们就拿到了 instanceB 的 bean
                     
                    Object fileObject = getBean(name);

                     为属性设置类型
                    declaredField.set(instanceBean,fileObject);
                }
            }


            *
             * 第四步: 初始化
             * 初始化就是设置类的init-method.这个可以设置也可以不设置. 我们这里就不设置了
             */


            *
             * 第五步: 放入到一级缓存
             *
             * 在这里二级缓存存的是动态代理,那么一级缓存肯定也要存动态代理的实例.
             * 从二级缓存中取出实例,放入到一级缓存中
             */
            if (earlySingletonObjects.containsKey(beanName)) {
                instanceBean = earlySingletonObjects.(beanName);
            }
            singletonObjects.put(beanName,instanceBean);

             删除二级缓存

             删除三级缓存
        }
         instanceBean;
    }

 

然后在从缓存取数据的getSingleton()上也加一把锁

private  Object getSingleton(String beanName) {
        先去一级缓存里拿,
        Object bean = singletonObjects.(beanName);
         一级缓存中没有,但是正在创建的bean标识中有,说明是循环依赖
        if (bean == null && singletonsCurrectlyInCreation.contains(beanName)) {
            synchronized (singletonObjects) {
                bean = earlySingletonObjects.(beanName);
                 如果二级缓存中没有,就从三级缓存中拿
                 从三级缓存中取
                    ObjectFactory objectFactory = singletonFactories.(beanName);
                    if (objectFactory != ) {
                         这里是真正创建动态代理的地方.
                        bean = objectFactory.getobject();
                         然后将其放入到二级缓存中. 因为如果有多次依赖,就去二级缓存中判断. 已经有了就不在再次创建了
                        earlySingletonObjects.put(beanName,bean);
                    }
                }
            }
        }
         bean;
    }

加了两把锁.

 

这样,在分析一下

 

如上图,线程B执行到getSingleton()的时候,从一级缓存中取没有,到二级缓存的时候就加锁了,他要等待直到线程A完成执行完才能进入. 这样就避免出现不完整bean的情况. 

 

三. 源码解决

在创建实例bean的时候,加了一把锁,锁是一级缓存.

 1 public Object getSingleton(String beanName,ObjectFactory<?> singletonFactory) {
 2         Assert.notNull(beanName,"Bean name must not be null");
 3         synchronized (this.singletonObjects) {
 4              第一步: 从一级缓存中获取单例对象
 5             Object singletonObject = this.singletonObjects.(beanName);
 6             if (singletonObject == ) {
 7                 if (this.singletonsCurrentlyInDestruction) {
 8                     throw  BeanCreationNotAllowedException(beanName,9                             Singleton bean creation not allowed while singletons of this factory are in destruction " +
10                             (Do not request a bean from a beanfactory in a destroy method implementation!));
11                 }
12                  (logger.isDebugEnabled()) {
13                     logger.debug(Creating shared instance of singleton bean '" + beanName + '1415                  第二步: 将bean添加到singletonsCurrentlyInCreation中,表示bean正在创建
16                 beforeSingletonCreation(beanName);
17                 boolean newSingleton = false;
18                 boolean recordSuppressedExceptions = (this.suppressedExceptions == 19                  (recordSuppressedExceptions) {
20                     this.suppressedExceptions = new LinkedHashSet<>();
2122                 try {
23                      第三步: 这里调用getobject()钩子方法,就会回调匿名函数,调用singletonFactory的createBean()
24                     singletonObject = singletonFactory.getobject();
25                     newSingleton = 2627                 catch (IllegalStateException ex) {
28                      Has the singleton object implicitly appeared in the meantime ->
29                      if yes,proceed with it since the exception indicates that state.
30                     singletonObject = (beanName);
31                     ) {
32                         throw ex;
33                     }
3435                  (BeanCreationException ex) {
36                     37                         for (Exception suppressedException : .suppressedExceptions) {
38                             ex.addRelatedCause(suppressedException);
39                         }
4041                     4243                 finally44                     45                         4647                     afterSingletonCreation(beanName);
4849                  (newSingleton) {
50                     addSingleton(beanName,singletonObject);
5152             }
53              singletonObject;
54         }
55     }

 

再从缓存中取数据的时候,也加了一把锁,和我们的demo逻辑是一样的. 锁也是一级缓存.

protected Object getSingleton(String beanName,boolean allowEarlyReference) {
         从一级缓存中获取bean实例对象
        Object singletonObject = *
         * 如果在第一级的缓存中没有获取到对象,并且singletonsCurrentlyIncreation为true,也就是这个类正在创建.
         * 标明当前是一个循环依赖.
         *
         * 这里有处理循环依赖的问题.-- 我们使用三级缓存解决循环依赖
         */
         isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                *
                 * 从二级缓存中拿bean,二级缓存中的对象是一个早期对象
                 * 什么是早期对象?就是bean刚刚调用了构造方法,还没有给bean的属性进行赋值,和初始化,这就是早期对象
                  

                singletonObject = this.earlySingletonObjects. allowEarlyReference) {
                    *
                     * 从三级缓存拿bean,singletonFactories是用来解决循环依赖的关键所在.
                     * 在ios后期的过程中,当bean调用了构造方法的时候,把早期对象包装成一个ObjectFactory对象,暴露在三级缓存中
                      
                    ObjectFactory<?> singletonFactory = this.singletonFactories.if (singletonFactory != *
                         * 在这里通过暴露的ObjectFactory包装对象. 通过调用他的getobject()方法来获取对象
                         * 在这个环节中会调用getEarlyBeanReference()来进行后置处理
                         
                        singletonObject = singletonFactory.getobject();
                         把早期对象放置在二级缓存中
                        .earlySingletonObjects.put(beanName,singletonObject);
                         删除三级缓存
                        .singletonFactories.remove(beanName);
                    }
                }
            }
         singletonObject;
    }

 

3.4 spring5源码系列--循环依赖的设计思想 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终

3.4 spring5源码系列--循环依赖的设计思想 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终

前面已经写了关于三篇循环依赖的文章,这是一个总结篇

第一篇: 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

第二篇: 3.2spring源码系列----循环依赖源码分析

第三篇: 3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终

现在总结循环依赖的思想

学了那么多,为什么说见多才能识广呢,知道别人是如何解决某一类问题的,也就是优秀代码的魅力. 这也是为什么要学习别人的代码的原因.

思想才是我们可以在工作中借鉴使用的

1. 循环依赖的三级缓存设计

2. 接口函数

 

 

一. 循环依赖的三级缓存设计

再循环依赖的过程中设计了三级缓存,他们的作用分别是

1. 一级缓存: 用来存放完整的bean

2. 二级缓存: 用来存放早期的,纯净的bean

3. 三级缓存: 用来存放接口函数.

   /** Cache of singleton objects: bean name to bean instance. */
    /**
     * 一级缓存  这个就是我们大名鼎鼎的缓存池,用于保存我们所有的实例bean
     private final Map<String,Object> singletonObjects = new ConcurrentHashMap<>(256);

    * Cache of singleton factories: bean name to ObjectFactory. *
     * 三级缓存  该map用户缓存key为beanName,value为objectFactory(包装为早期对象)
     singletonFactories = new HashMap<>(16* Cache of early singleton objects: bean name to bean instance. *
     * 二级缓存,用户缓存我们的key为beanName,value是我们的早期对象(此时对象属性还没有...)
     earlySingletonObjects = 16);

 

细细想来,这三个缓存都非常有存在的必要.

1.1 引入一级缓存

刚开始,只有一级缓存,在整个bean创建完成以后,将其完整的bean放入到一级缓存中. 这样有什么问题? 

1. bean创建一共有三大步骤,(实例化,属性赋值,初始化) 等到整个过程都创建完,在存入一级缓存,多线程怎么办? 第一个线程创建bean的过程中,又来了一个线程,他发现一级缓存这时候还没有,就回去再次创建. 那不就重复了么? ioc要求,bean是单例的.

2. 加锁,加锁能否解决这个问题? 能,但是效率超级低. 对一级缓存加锁,那么所有的对象创建过程中都要等待. 哪怕人家已经创建成功过. 效率太低,不能接受

3. 于是就引入了二级缓存. 

1.2 引入二级缓存

二级缓存的引入,可以解决一级缓存创建bean链路过长的问题,他在bean一旦被创建,立刻就放入到二级缓存. 整个bean创建完成以后,在放入到一级缓存,删除二级缓存. 这样做可以解决多线程创建bean的问题. 缩短了整个链路. 同时,每次从缓存中先获取bean,如果一级缓存中已经有了,那么直接返回. 不用在执行后面的创建代码

那么,二级缓存有什么问题呢?

这就还需要知道一个问题,那就是动态代理创建bean. 什么时候,去使用动态代理创建bean? 通常我们说在初始化之后,调用bean的后置处理器创建bean. 这只是大多数bean创建动态代理的时候. 那如果有循环依赖呢? 有循环依赖,还在初始化之后创建就晚了. 这是需要在实例化之后创建. 这样,动态代理的代码就和创建bean耦合在一块了. 违背单一性原则.

于是,引入了三级缓存

1.3 引入三级缓存

三级缓存的引入是为了解决耦合问题. 让每一个方法只做一件事. 巧妙的使用了接口函数. 

 这个接口函数什么用呢? 就相当于js中的回调函数. 我在前面定义好,但是不执行. 直到满足条件了,才执行. 这个方法,可以大范围应用到实践工作中.

比如: 调用动态代理创建bean. 刚开始实例化完成以后,我就赋予你这个能力,你可以调用动态代理. 但是,到后面,你是否真的能够运用这个能力呢? 不一定,只有满足条件,才会运用这个能力. 

二. 定义接口函数,也叫钩子函数

在循环依赖源码中,两次使用到接口函数的方式. 

第一个是创建bean的时候. 第二个是三级缓存

下面来看看源码,

第一次: 创建bean的时候,定义了一个钩子函数createBean()

sharedInstance = getSingleton(beanName,() -> {
    try {
        // 这里定义了一个钩子函数. 此时只是定义,并不执行. 在真正需要创建bean的地方才会执行
        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;
    }
});

实际上调用的时机是: 在getSingleton方法里面. 回调接口函数.

public Object getSingleton(String beanName,ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName,"Bean name must not be null");
        synchronized (this.singletonObjects) {
             第一步: 从一级缓存中获取单例对象
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,1)">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 + ' 第二步: 将bean添加到singletonsCurrentlyInCreation中,表示bean正在创建
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == );
                 (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                 {
                    // 第三步: 这里调用getobject()钩子方法,就会回调匿名函数,调用singletonFactory的createBean()
                    singletonObject = singletonFactory.getobject();
                    newSingleton = true;
                }
                 (IllegalStateException ex) {
                     Has the singleton object implicitly appeared in the meantime ->
                     if yes,proceed with it since the exception indicates that state.
                    singletonObject = (beanName);
                    ) {
                        throw ex;
                    }
                }
                 (BeanCreationException ex) {
                     (recordSuppressedExceptions) {
                        for (Exception suppressedException : .suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                     ex;
                }
                finally {
                    ;
                    }
                    afterSingletonCreation(beanName);
                }
                 (newSingleton) {
                    addSingleton(beanName,singletonObject);
                }
            }
             singletonObject;
        }
    }

 

第二次调用: 是在三级缓存定义的时候

调用addSingletonFactory(...)定义了一个钩子函数. 这里仅仅是定义,并不执行

 把我们的早期对象包装成一个singletonFactory对象,该对象提供了getobject()方法,把静态的bean放到三级缓存中去了.
addSingletonFactory(beanName,() -> getEarlyBeanReference(beanName,bean));

然后进入到addSingletonFactory内部,只是把singletonFactory放入到了三级缓存中,这里只是定义,也并没有执行

protected void addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory,1)">Singleton factory must not be nullif (!.singletonObjects.containsKey(beanName)) {
                 加入到三级缓存中,暴露早期对象用于解决循环依赖.
                this.singletonFactories.put(beanName,singletonFactory);

                 从二级缓存中删除
                .earlySingletonObjects.remove(beanName);

                 添加到已经注册的singleton实例.
                .registeredSingletons.add(beanName);
            }
        }
    }

什么时候执行的呢? 再从缓存中获取对象的时候. 

@Nullable
    protected Object  从一级缓存中获取bean实例对象
        Object singletonObject = (beanName);
        *
         * 如果在第一级的缓存中没有获取到对象,并且singletonsCurrentlyIncreation为true,也就是这个类正在创建.
         * 标明当前是一个循环依赖.
         *
         * 这里有处理循环依赖的问题.-- 我们使用三级缓存解决循环依赖
         */
        null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (.singletonObjects) {
                *
                 * 从二级缓存中拿bean,二级缓存中的对象是一个早期对象
                 * 什么是早期对象?就是bean刚刚调用了构造方法,还没有给bean的属性进行赋值,和初始化,这就是早期对象
                  */

                singletonObject = this.earlySingletonObjects.(beanName);
                 allowEarlyReference) {
                    *
                     * 从三级缓存拿bean,singletonFactories是用来解决循环依赖的关键所在.
                     * 在ios后期的过程中,当bean调用了构造方法的时候,把早期对象包装成一个ObjectFactory对象,暴露在三级缓存中
                      */
                    ObjectFactory<?> singletonFactory = this.singletonFactories.(beanName);
                    if (singletonFactory != ) {
                        /**
                         * 在这里通过暴露的ObjectFactory包装对象. 通过调用他的getobject()方法来获取对象
                         * 在这个环节中会调用getEarlyBeanReference()来进行后置处理
                         */
                        singletonObject = singletonFactory.getobject();
                         把早期对象放置在二级缓存中
                        .earlySingletonObjects.put(beanName,singletonObject);
                         删除三级缓存
                        .singletonFactories.remove(beanName);
                    }
                }
            }
        }
         singletonObject;
    }

在这里调用三级缓存, singletonObject = singletonFactory.getobject(); 回调钩子函数. 

关于Spring IOC源码笔记-SpringBean的实例化spring的ioc源码解析的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于1. spring5源码系列 -- Spring整体脉络 IOC加载过程 Bean的生命周期、2014-03-09 Spring的学习(1)------Spring管理Bean(实例化Bean)、3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析、3.4 spring5源码系列--循环依赖的设计思想 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖3.2spring源码系列----循环依赖源码分析3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终的相关知识,请在本站寻找。

本文标签: