Spring IOC

84 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情

容器初始化流程

1.容器初始化流程.jpg

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

      // Prepare this context for refreshing.
      prepareRefresh();

      // 创建BeanFactory对象,xml解析,封装成BeanDefinition对象。这里是通过springboot启动的(不通过xml配置bean),所以在SpringApplication方法中创建context的时候就创建了befactory。
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // BeanFactoryPostProcessor会修改或添加BeanDefinition,比如@EnableAutoConfigurationImportSelector扫描到所有自动装配Configuraction并对其BeanDefinition进行注册。
         invokeBeanFactoryPostProcessors(beanFactory);

         // registerBeanPostProcessors(beanFactory):只是注册到BeanFactory中,具体调用是在bean初始化的时候。在所有bean实例化时,执行初始化方法前会调用所有BeaPostProcessor的postProcessBeforeInitialization方法,在执行初始化方法后会调用所有BeanPostProcessor的postProcessAfterInitialization方法(比如使用APC生成代理)。
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();

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

         // 初始化事件multicaster
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // 注册事件
         registerListeners();

         //初始化所有剩余(非懒加载)单例
         finishBeanFactoryInitialization(beanFactory);

         // 最后步骤,发布相应的时间
         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();
         contextRefresh.end();
      }
   }
}
  1. obtainFreshBeanFactory():创建BeanFactory对象,xml解析,封装成BeanDefinition对象。这里是通过springboot启动的(不通过xml配置bean),所以在SpringApplication方法中创建context的时候就创建了benfactory。
  2. invokeBeanFactoryPostProcessors(beanFactory):BeanFactoryPostProcessor会修改或添加BeanDefinition,比如@EnableAutoConfiguration的@Import导入的AutoConfigurationImportSelector扫描到所有自动装配Configuraction并对其BeanDefinition进行注册。
  3. registerBeanPostProcessors(beanFactory):只是注册到BeanFactory中,具体调用是在bean初始化的时候。在所有bean实例化时,执行初始化方法前会调用所有BeaPostProcessor的postProcessBeforeInitialization方法,在执行初始化方法后会调用所有BeanPostProcessor的postProcessAfterInitialization方法(比如使用APC生成代理)。
  4. finishBeanFactoryInitialization(beanFactory):初始化所有剩余(非懒加载)单例。

总体来说就是先创建BeanFactory,后面扫描Bean拿到所有BeanDefinition,再注册Bean初始化需要的BeanPostProcessors,后面就开始初始化Bean。

我们下面看看BeanDefinition的具体内容和如何创建Bean的。

BeanDefinition

因为笔者读过Mybatis源码,所以我们来看看dao的BeanDefinition是如何生成的。(具体可以查看《Mybatis(Plus)源码阅读路径》

下面我们大概看看,入口就是@MapperScan的@Import的处理类 MapperScannerRegistrar。

image.png 这里为扫描dao后拿到的BeanDefinition,可以看到是我们刚刚提到的AbstractApplicationContext#refresh调用invokeBeanFactoryPostProcessors(beanFactory)扫描拿到BeanDefinition。

我们继续看看processBeanDefinitions(beanDefinitions);对BeanDefinition的修改。

image.png

可以看到把dao统一修改成org.mybatis.spring.mapper.MapperFactoryBean把原始类改成了构造函数的参数,和后面使用动态代理生成Mapper是对应的。

我们大概罗列下BeanDefinition的属性:

  • metadata(className、supperClassName、interfaceNames、annotationType)

image.png

  • beanClass

image.png

  • scope、lazyInit、dependsOn、factoryBeanName

image.png

  • genericArgumentValues、propertyValues、initMethodName、destoryMethodName

image.png

  • resource、source、beanName

image.png

AbstractBeanFactory#getBean——创建bean

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {

   String beanName = transformedBeanName(name);
   Object beanInstance;

   // 主动检查单例缓存是否有手动注册的单例。
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      //如果bean实例还在创建中(大概率循环引用),则直接抛出异常
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // 如果 bean definition 存在于父的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 if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      if (!typeCheckOnly) {
         // 将当前bean实例放入alreadyCreated集合里,标识这个bean准备创建了 
         markBeanAsCreated(beanName);
      }

      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
      try {
         if (requiredType != null) {
            beanCreation.tag("beanType", requiredType::toString);
         }
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // 确保它的依赖也被初始化了.
         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 {
                  // 获得依赖的bean 
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         //创建Bean实例:单例
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  //创建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;
               }
            });
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         else {
            String scopeName = mbd.getScope();
            if (!StringUtils.hasLength(scopeName)) {
               throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
            }
            Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new ScopeNotActiveException(beanName, scopeName, ex);
            }
         }
      }
      catch (BeansException ex) {
         beanCreation.tag("exception", ex.getClass().toString());
         beanCreation.tag("message", String.valueOf(ex.getMessage()));
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
      finally {
         beanCreation.end();
      }
   }

   return adaptBeanInstance(name, beanInstance, requiredType);
}

我们直接来看看

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;
      }
   });
   beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

是如何创建Bean的。

image.png

可以看到是根据BeanDefinition的内容进行反射出来的。如下:

Class<Order> orderClass = (Class<Order>) Class.forName("Order");
Constructor<Order> constructor = orderClass.getConstructor();
Order o = constructor.newInstance();
o.setTotalCount(1);

所以Bean的创建本质还是依赖于反射的,下面我们看看构造过程中如何使用三级缓存解决循环依赖的。

三级缓存

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  • 第一层缓存(singletonObjects):单例对象缓存池,已经实例化并且属性值复制,这里的对象是成熟对象
  • 第二层缓存(earlySingletonObjects):单例对象缓存池,已经实例化但尚未属性赋值,这里的对象是半成品对象
  • 第三层缓存(singletonFactories):单例工厂的缓存。

例子:

package com.study.spring.service.impl;

import com.study.spring.dao.TestDao;
import com.study.spring.entity.TestDo;
import com.study.spring.service.TestService;
import com.study.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("testService")
public class TestServiceImpl extends ServiceImpl<TestDao, TestDo> implements TestService {
    @Autowired
    private UserService userService;

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    public void test() {
        throw new RuntimeException();
    }
}
package com.study.spring.service.impl;

import com.study.spring.dao.UserDao;
import com.study.spring.service.TestService;
import com.study.spring.service.UserService;
import com.study.spring.entity.UserDo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserDo> implements UserService {
    @Autowired
    private TestService testService;

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    public void test() {
        UserDo userUpdate = new UserDo();
        userUpdate.setId(1L);
        userUpdate.setUserName("ff");
        this.updateById(userUpdate);
        throw new RuntimeException();
    }
}

可以看到上面会产生循环依赖。

image.png 这里会先创建testService。

存放第三级缓存

AbstractBeanFactory#doCreateBean

if (earlySingletonExposure) {
   if (logger.isTraceEnabled()) {
      logger.trace("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
   }
   addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

放入的是一个函数接口对象,可以看到持有了beanName、mbd、bean(前面通过beanDefinition反射创建的)。

DefaultSingletonBeanRegistry#addSingletonFactory

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   synchronized (this.singletonObjects) {
      if (!this.singletonObjects.containsKey(beanName)) {
         this.singletonFactories.put(beanName, singletonFactory);
         this.earlySingletonObjects.remove(beanName);
         this.registeredSingletons.add(beanName);
      }
   }
}

image.png

populateBean——填充属性

image.png testService存放好第三级缓存后进行填充属性。

image.png 因为testService注入了userService,所以开始创建userService。

存放第二级缓存

image.png userService也开始填充属性。

image.png 因为userService注入了testService,所以开始处理。

image.png 可以看到使用AbstractFactory#getBean开始获取testService,因为之前已经放入三级缓存,所以从中取出放入二级缓存,此时放入二级缓存中的已经是代理对象。

image.png 后面会直接返回代理对象,userService填充完属性后返回。

存放一级缓存

image.png 继续创建testService。

image.png 调完函数接口后继续执行内部。

image.png 最后放入一级缓存。

总结

可以看到,在创建testService的时候会先把单例工厂放入三级缓存,放好之后会进行populateBean属性,填充属性的时候如果出现和属性循环依赖就会从singletonFactories从取出单例工厂实例化(如果是代理就生成代理对象),之后放入二级缓存,populateBean属性后会返回二级缓存实例用来放入第一级缓存。

可以发现二三级缓存只有循环依赖发生时才会用上(虽然三级缓存会put但是没用上),没有循环依赖就等填充好属性后如果有代理直接使用beanpostprocessor进行生成代理对象后放入一级缓存。

生命周期

image.png