Spring的IOC初始化流程

  • Spring的出现就是为了更好的管理Bean,而IOC/DI/DL又是Spirng的核心,IOC在Spring中可以简单的理解为一个Map容器,帮我们管理控制着Bean的生命周期。
  • IOC -Inversion of control:控制反转,不是什么技术,而是一种设计思想,把对象的使用和创建分开了。

1、理解IOC/DI/DL

一切从Bean开始,IOC其实就是对我们的Bean进行管理;例如Bean加载,实例化,注册和管理。
例如,拿我们的SpringMVC为例,spring MVC本质上就是一个servlet,遵循了servlet的规范;在启动tomcat的时候,init()方法会完成以下工作:
  • 第一步:JVM会扫描我们的jar或者war包,读取加载配置class文件,进行环境等变量的准备配置;
  • 第二步:继续扫描业务字节码文件,包括相关的类,注解等class文件的全路径;
  • 第三步:把第二步扫描出来的类通过反射进行实例化instance,然后注册到 IOC容器Map中;
  • 第四步:完成 依赖查找注入DL 和 DI,实例化之后bean与bean之间的关系;例如加了@Resource @Autowire等注解的变量关系;
  • 第五步:完成HandlerMapping的初始化,将加了@Controller和@RequestMapping的注解的url和method关系缓存到Map容器中;
  • 第六步:容器启动完成,可以使用;
其中的3-4-5步骤都是在进行IOC的实现,将bean交给Spring容器托管。
 
继续理解什么是IOC/ID/DL,通过一段经常见的小代码来简单解释分析一下:
常见的Bean配置类:
@Configuration //配置类
public class AutowiredPersonConfig {
   
    @Bean
    public Person person(){
        return new Person();
    }

}

功能代码实现的:IOC ,依赖注入和依赖查找。

@SpringBootApplication
public class SpringBootMainApp {

    @Resource //DI 依赖注入
    private Person person;

    public static void main(String[] args) {
       
        //IOC,所谓的控制反转,容器载入类,将Bean实例化,然后交给spring容器Map托管;
        ApplicationContext app = new AnnotationConfigApplicationContext(AutowiredPersonConfig.class);
  
        //DL 依赖查找,在容器中查找id=person的Bean实例对象;
        Person person = (Person) app.getBean("person");
        // TODO HERE
    }
}

分析:容器启动载入类AnnotaionConfigApplicationContext完成Bean的装载和注册,@Resource里面就简单的实现了bean的依赖查找和注入。

1.1、IOC -(Inversion Of Control)

    IOC-控制反转, 简单理解就是一个大的Map集合,主要用来存放Bean对象,new Person();  根据容器载入类来加载Bean对象;
    Spring的IOC有很多的Map容器。例如上面的代码,当服务在启动的时候,JVM会扫描我们的jar包,找到class文件中的配置类AutowiredPersonConfig.class,然后将相关加了@Configuratio和@Bean注解的实例Bean Person加入到容器map中,实际等价于做了如下操作:
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
singletonObjects.put("person",new Person());

没有IOC之前,我们要使用对象的时候就需要自己先创建一个对象,自己控制对象的生产,获取相应的资源,另外每次产生一个对象就会往JVM内存中写入一些数据,占用了内存,也增加垃圾回收的行能消耗;

但是有了IOC之后,管理和控制就发生了反转:
  • 控制了什么?对象的new创建和生命周期,相关的依赖资源获取;
  • 反转给谁?管理权反转给Spring,由Spring的 ioc容器来控制Bean生命周期;
这个简单的过程其实就是IOC的过程,
 

1.2、DL-(Dependency looking )

DI-依赖查找。完成了Bean的加载,实例化和注册后,当我们要使用的时候,也就是依赖查找与注入的过程:
@Resource //DI&DL 依赖查找&注入
private Person person;

实际上等价于执行了下面代码:

第一步:判断是否加了相关的注解信息:
先判断如果变量加了@Resource注解
if (field.isAnnotationPresent(Resource.class)) {
    //todo 进行属性赋值;
}

第二步:完成DL-依赖查找,从容器map中获取实例Bean Person:

Person person = singletonObjects.get("person");

1.3、DI-(Dependency injection )

第三步:完成DI-依赖注入,通过反射将第一步从容器map中取到的person值设置到 private Person person; 这个变量中。
从MAP容器中获取Person对应的bean实例,并注入到变量person中,完成依赖注入:
field.setAccessible(true);
field.set(personInstance, person));

其实这也就是完成了person实例变量的依赖查找和注入过程。

2、Spring容器启动流程

下面来看一下Spring容器启动的主要流程:
ioc容器的初始化与Bean的创建
  • 第一步: refresh,容器刷新启动的时候,读取扫描jar/war包中的启动类配置文件bean.xml,载入类和application.properties文件;
  • 第二步: 实例化BeanFactory这个Spring的最顶层的容器接口,创建完beanFactory,Spring就有了生产和获取getBean()的能力;另外,BeanFactory还提供一些后置处理器来保证我们的单实例非懒加载的业务bean正确创建;声明顶层map容器,初始化BeanFactory,使容器有getBean的能力;
  • 第三步: finishBeanFactoryInitialization,对剩下的非懒加载单实例业务Bean进行实例化,继续扫描我们的jar或者war包,class文件,得到加了@Controller/@Component/@Service/@Repository等注解的所有要实例化的Bean的全路径名beanDefinationName;
  • 第四步:通过BeanName开始从缓存也就是ioc容器map中直接获取bean实例:通过getBean()-doGetBean() ->getSingleton("beanName") —> map.getBean ("beanName"),先看IOC容器map缓存中是否有我们的singletonBean,有就 直接return,流程结束;
如果map缓存中没已实例化的Bean,则进行创建
  • 第一步:创建对象 createBean (),拿到class类对象,通过反射得到构造函数, 创建对象,new Person();
  • 第二步:属性赋值 populateBean():person. setName("king")
  • 第三步:执行初始化方法 initializeBean ,代理对象通过applyBeanPostProcessorsBeforeInitializatio napplyBeanPostProcessorsAfterInitialization进行增强bean的初始化前后增强
  • 至此,bean的创建完成,将单实例bean注册到ioc容器map中;
  • finishRefresh();Spring发送容器事件消息,我启动完成了,你可以做事情了;

3、Spring容器启动源码分析

下面通过源码具体分析一下Spring容器启动的主流程,从容器刷新开始:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
   this();
   register(annotatedClasses);
   refresh(); //统一入口
}

refresh() 刷新开始:
@Override //容器刷新入口:
public void refresh() throws BeansException, IllegalStateException {
    //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      //1、告诉子类启动refreshBeanFactory()方法,实例化创建BeanFactory,用来获取和创建Bean;
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      //为BeanFactory配置容器特性,例如类加载器、事件处理器等
      prepareBeanFactory(beanFactory);

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

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         //aop相关bean的创建
         //为BeanFactory注册BeanPost事件处理器.和业务bean执行的时机不一样而已,其他都一样;
         //BeanPostProcessor是Bean后置处理器的创建,用于监听容器触发的事件
         registerBeanPostProcessors(beanFactory);

         // Check for listener beans and register them.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         //2、初始化所有剩余的非懒加载的单实例 — 业务Bean—也就是java中写的Bean文件;
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         //容器创建完成,为什么是finish,因为spring中有很多的事件监听机制,告诉监听者我启动完了,你可以做一些事情了;
         finishRefresh();
      }

开始创建非懒加载的单实例业务Bean:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // Initialize conversion service for this context.
   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));
   }

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

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

   // Instantiate all remaining (non-lazy-init) singletons.
   //实例化所有剩下的非懒加载单实例业务Bean
   beanFactory.preInstantiateSingletons();
}

得到所有需要实例化的单实例Bean的全路径名,bean信息的定义 -用来生成这个bean的,然后挨个循环实例化:

@Override
public void preInstantiateSingletons() throws BeansException {

    String FACTORY_BEAN_PREFIX = "&";

   //得到所有的需要实例化的Bean的名字
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans…
    //挨个循环获取或者创建这个beanName;
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         if (isFactoryBean(beanName)) {
            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 {//获取或者创建这个bean
            getBean(beanName);
         }
      }
   }

在创建一个bean之前,先到ioc容器map中去获取相关的bean,如果该bean已经创建,则直接获取返回,不再创建,如果容器map中没有,则进行创建。这也是单例的体现,只创建一次,每次获取的对象都是同一个,可以验证打印它的地址是相同的。


@Override //获取bean信息
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
   return doGetBean(name, requiredType, null, false);
}
继续获取bean:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

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


    //将bean标记为已创建
    if (!typeCheckOnly) {
       markBeanAsCreated(beanName);
    }
   // Eagerly check singleton cache for manually registered singletons.
    //通过bean的名字到我们的 IOC大map-其实就是一个缓存 中获取 bean;
   Object sharedInstance = getSingleton(beanName);
    //如果缓存中有这个bean,则直接返回;
    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 + "'");
          }
       }
       bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    //如果缓存中没有这个bean,则直接开始创建这个bean;
    else {
    if (mbd.isSingleton()) {
       sharedInstance = getSingleton(beanName, () -> {
          try {
             return createBean(beanName, mbd, args);
          }

从缓存容器map中获取bean单实例;

//private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //直接在map中get
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) { //同步获取;
         singletonObject = this.earlySingletonObjects.get(beanName);
         if (singletonObject == null && allowEarlyReference) {
            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
    //如果容器中有bean,则直接返回;
   return singletonObject;
}

如果容器中有这个单实例bean则直接返回创建的流程结束;如果缓存中还没有我们需要的实例Bean,这时候就会开始创建我们的Bean实例:

创建createBean实例的具体步骤:
  • 第一步:通过反射创建对象,new Person();
  • 第二步:属性赋值;person.set("king")
  • 第三步:执行Bean初始化方法,对于动态代理的对象Bean进行init前后拦截增强;
具体实现如下:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

     try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        //给个机会返回一个代理对象,这里什么都没做,因为aop的bean是普通的bean的创建过程;
       Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
       if (bean != null) {
          return bean;
       }
    }

   // 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);
    try {
        //开始创建
       Object beanInstance = doCreateBean(beanName, mbdToUse, args);
       if (logger.isTraceEnabled()) {
          logger.trace("Finished creating instance of bean '" + beanName + "'");
       }
       return beanInstance;
}

创建bean,这里已经有内存地址了,也就是完成了对象的实例化:

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);
   }
   if (instanceWrapper == null) { 
      //这里bean先创建对象,已经有内存地址;相当于Person person = new Person();
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }

Spring是通过反射来创建对象,通过createBeanInstance()发现具体创建对象步骤如下:

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
   // Don't override the class with CGLIB if no overrides.
   if (!bd.hasMethodOverrides()) {
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                    //反射获取构造函数
                  constructorToUse = clazz.getDeclaredConstructor();
            }
            catch (Throwable ex) {
               throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            }
         }
    }
        //第一步:反射创建实例完成 等价于Person person = new Person();
      return BeanUtils.instantiateClass(constructorToUse);
   }
    Object exposedObject = bean;
    try {
        //第二步:属性的赋值和初始化,等价于 person.setName("king");
       populateBean(beanName, mbd, instanceWrapper);
        //第三步:bean的初始化
       exposedObject = initializeBean(beanName, exposedObject, mbd);
    }

initializedBean主要是对bean完成一些初始化工作,比如在做动态代理的时候,这里就用到了,对当前的Bean初始化执行前和执行后做一些增强的处理工作,   

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
       AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
          invokeAwareMethods(beanName, bean);
          return null;
       }, getAccessControlContext());
    }
   else {//对bean的初始化
      invokeAwareMethods(beanName, bean);
   }
    Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
        //对bean出世化的前置处理器
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }
   if (mbd == null || !mbd.isSynthetic()) {
        //对bean初始化的后置处理器
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

至此,一个业务bean的实例化就完成了,结束之后,将这个bean放入到我们的IOC容器map中去,供后期业务 DI/DL使用;

 

4、小结

        IOC的主要任务就是创建对象Bean,同时通过DL和DI处理Bean之间的关联关系,创建的这些单例对象,所有线程共享,一次创建,到处使用。集中管理,统一分配,减少内存开销。
 
 
 
水滴石穿,积少成多。学习笔记,内容简单,用于复习,梳理巩固。
 
参考资料:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值