一、前言

    话说最近咱们组疯狂招人中,组里的几位资深大佬在疯狂面试,从早到晚就是在语音和视频,昨晚要加班,下楼跟大手子们去吃饭,聊起面试情况,一位大佬VV哥开始疯狂输出:“我这面试一天,基本上没几个能把Spring的加载过程说清楚的,基本上一问就支支吾吾,现在这API调用工程师太多了”,另一位大佬脏脏哥疯狂附和,我在一边听到流下了没有技术的“冷汗”,这......不就是说的我嘛,每天写写业务代码,调调接口,写写SQL,搞搞TestCase,属实是最底层的搬砖工,疯狂扒拉两口饭,立马逃离大型审判现场,跑到工位坐下开始 看!源!码!整活~菜狗要翻身!

二、体系

   那其实讲到Spring,我们可以这么看:

   因为Spring 最初利用“工厂模式”( DI )和“代理模式”( AOP )解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个 MVC 框架(一些用 Spring 解耦的组件),用开发 web 应用( SpringMVC)。然后呢,又发现每次开发都要搞很多依赖,写很多样板代码很麻烦,那就很烦躁了,于是乎大牛们就搞了一些懒人整合包( starter ),这套玩意就是 Spring Boot ,具体介绍如下:

  1. Spring是一个一站式的轻量级的java开发框架,核心是控制反转(IOC)和面向切面(AOP),针对于开发的WEB层(springMvc)、业务层(Ioc)、持久层(jdbcTemplate)等都提供了多种配置解决方案;  
  2. SpringMVC是spring基础之上的一个MVC框架,主要处理web开发的路径映射和视图渲染,涵盖面包括前端视图开发、文件配置、后台接口逻辑开发等,XML、config等配置相对比较繁琐复杂,属于spring框架中WEB层开发的一部分;,
  3. Spring Boot使用了默认大于配置的理念,集成了快速开发的Spring多个插件,同时自动过滤不需要配置的多余的插件,简化了项目的开发配置流程,一定程度上取消xml配置,是一套快速配置开发的脚手架,能快速开发单个微服务;

三、开搞开搞

     废话不多说了,现在就跟大家来一次对Spring的源码追踪一波,本菜狗今天就要看一看Spring到底是怎么进行的初始化的,它如何创建的bean,我们这次就从spring-boot-1.5.13进行追踪一步步往下看吧;

1.默认的spring启动器,直接从这个地儿进去,没毛病:

public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}复制代码

2.这里创建了一个SpringApplication,执行了一个run方法,返回的是一个ConfigurableApplicationContext,这只是一个接口,根据他的命名来看的话,是一个可配置的应用上下文对象;

下面的run方面看起来就是我们要看的重点吧?Emmmm....不慌不慌,继续往下点就完事了;

/**
 * Static helper that can be used to run a {@link SpringApplication} from the
 * specified source using default settings.
 * @param source the source to load
 * @param args the application arguments (usually passed from a Java main method)
 * @return the running {@link ApplicationContext}
 */public static ConfigurableApplicationContext run(Object source, String... args) {
   return run(new Object[] { source }, args);
}

/**
 * Static helper that can be used to run a {@link SpringApplication} from the
 * specified sources using default settings and user supplied arguments.
 * @param sources the sources to load
 * @param args the application arguments (usually passed from a Java main method)
 * @return the running {@link ApplicationContext}
 */
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
   return new SpringApplication(sources).run(args);
}复制代码

 

3.进去run方法后,哦豁,这一大堆玩意儿,也不知道这都是些啥,哎,硬着头皮往下看吧,冲!兄弟们!

/**
 * Run the Spring application, creating and refreshing a new
 * {@link ApplicationContext}.
 * @param args the application arguments (usually passed from a Java main method)
 * @return a running {@link ApplicationContext}
 */
public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
   SpringApplicationRunListeners listeners = getRunListeners(args);
   listeners.starting();
   try {
       //参数封装,在命令行下启动应用带的参数
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
       //
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      Banner printedBanner = printBanner(environment);
      context = createApplicationContext();
      analyzers = new FailureAnalyzers(context);
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}复制代码

3.嗨呀,乍一看好像也就这么些东西,核心的东西都在try{}里面,我们一个个看,前面几行就是获取args参数和准备获取一些环境配置的东西,问题不大;

 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
 ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);复制代码

4.接下来,嘿,好家伙,开始创建context对象了,看到context = createApplicationContext这行;

context = createApplicationContext();复制代码

然后进入,因为我们刚刚在创建ConfigurableApplicationContext时并没有给 context赋值,所以此时context = null,那么便会创建指定的两个applicationContext中的一个,返回一个刚刚创建的context,这个context便是我们的基础,因为咱们现在为web环境,所以创建的context为 AnnotationConfigEmbeddedWebApplicationContext。

protected ConfigurableApplicationContext createApplicationContext() {
   Class<?> contextClass = this.applicationContextClass;
   if (contextClass == null) {
      try {
         contextClass = Class.forName(this.webEnvironment
               ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Unable create a default ApplicationContext, "
                     + "please specify an ApplicationContextClass",
               ex);
      }
   }
   return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}

public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."
      + "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";

private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
      "org.springframework.web.context.ConfigurableWebApplicationContext" };
复制代码

5.这些事干完之后,就到了准备上下文了;

 prepareContext(context, environment, listeners, applicationArguments,printedBanner);
复制代码
private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
 
    //设置context上下文的environment,简单 设置环境相关的配置呗
   context.setEnvironment(environment);
    // 应用上下文后处理
   postProcessApplicationContext(context);
    //在context refresh之前,对其应用ApplicationContextInitializer
   applyInitializers(context);
   // 上下文准备(这个里面是空实现,这是Spring预留扩展用的)
   listeners.contextPrepared(context);
    // 打印启动日志和启动应用的Profile
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }

   // Add boot specific singleton beans
   context.getBeanFactory().registerSingleton("springApplicationArguments",
         applicationArguments);
   if (printedBanner != null) {
      context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
   }

   // Load the sources
   Set<Object> sources = getSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   load(context, sources.toArray(new Object[sources.size()]));
   listeners.contextLoaded(context);
}复制代码

6.上面这些看完好像也没啥,接下来,重头戏应该要来了吧;

refreshContext(context);复制代码

这个方法好像有点狠,看着架势是用来准备容器和刷新应用上下文的,咱们点进去看看;

private void refreshContext(ConfigurableApplicationContext context) {
   refresh(context);
   if (this.registerShutdownHook) {
      try {
         context.registerShutdownHook();
      }
      catch (AccessControlException ex) {
         // Not allowed in some environments.
      }
   }
}复制代码

诶,还有个方法,继续点进去;

protected void refresh(ApplicationContext applicationContext) {
   Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
   ((AbstractApplicationContext) applicationContext).refresh();
}复制代码

Emmmmm...乖乖,都是AbstractApplicationContext.class是这个玩意在从中作梗,咱们继续进去!冲!

PS:只要我们进入了refresh(context)这个方法,不管进入哪一个实现类,最终进入的都是AbstractApplicationContext.java这个类:

来到了我们的核心,AbstractApplicationContext类,refresh方法就很贴心,里面每个方法干了啥都有注释,这就很舒服,减少了咱们理解的难度(这时候坐我旁边的粉粉同学看到了就开始小声bb:这英文注释就很烦,在下立***势回怼:快,赶紧装个翻译插件去,快,跑步前进~);

@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.
      //简单的获取beanFactory
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      //将context中的一些属性设置到beanFactory中 
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         //这个地方空实现,也没干啥,Spring预留的扩展
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         //解析配置文件、生成所有的beanDefinitions
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         //分类、排序、注册(注入)所有的BeanPostProcessors,用于处理 bean 的初始化流程
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         //这玩意就是用来做国际化的
         initMessageSource();

         // Initialize event multicaster for this context.
         //注册 applicationEventMulticaster SingletonBean
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         //这里主要创建和初始化容器
         onRefresh();

         // Check for listener beans and register them.
        //检查***bean并注册它们
         registerListeners();

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

         // Last step: publish corresponding event.
         //大功告成,然后开启Web容器
         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();
      }
   }
}复制代码

上面这些代码总结一波:

其实上面的方法中,我们需要比较注意的地方有两个,其实加载bean主要是在这两个方法里面取做的,我们看代码:

1.invokeBeanFactoryPostProcessors(beanFactory);

2.finishBeanFactoryInitialization(beanFactory);

我们进入invokeBeanFactoryPostProcessors,然后继续走着,找到这一行

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());复制代码

然后继续在这个方法中找到

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);复制代码

进入到该方法内部里面之后,有一个循环,进入内部方法 :

postProcessor.postProcessBeanDefinitionRegistry(registry)

此时传入的registry就是我们context中的beanfactory,因为其实现了BeanDefinitionRegistry接口,而此时的postProcessor实现类为ConfigurationClassPostProcessor.java

/**
 * Derive further bean definitions from the configuration classes in the registry.
 */
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
   int registryId = System.identityHashCode(registry);
   if (this.registriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
   }
   if (this.factoriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + registry);
   }
   this.registriesPostProcessed.add(registryId);

   processConfigBeanDefinitions(registry);
}复制代码

进入之后直接看最后面的一个方法,名称为processConfigBeanDefinitions(registry),翻译一波就是用来配置beanDefinitions的流程。

OK,我们继续点进去,这里代码过于长,咱们就不贴了8~~~(偷一波懒);

 

在processConfigBeanDefinitions(registry)里,在301行代码会获取一个解析器,代码如下:

ConfigurationClassParser parser = new ConfigurationClassParser(     --301行
      this.metadataReaderFactory, this.problemReporter, this.environment,
      this.resourceLoader, this.componentScanBeanNameGenerator, registry);复制代码

 

parser.parse(candidates);  --308行复制代码

然后308行会执行parser的parse方法,进入parse方法之后,会发现内层还有parse方法,不要紧,继续进入内层的parse,然后发现有个for循环;

for (BeanDefinitionHolder holder : configCandidates) {
   BeanDefinition bd = holder.getBeanDefinition();
   try {
      if (bd instanceof AnnotatedBeanDefinition) {
         parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
      }
      else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
         parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
      }
      else {
         parse(bd.getBeanClassName(), holder.getBeanName());
      }
   }复制代码
protected final void parse(String className, String beanName) throws IOException {
   MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
   processConfigurationClass(new ConfigurationClass(reader, beanName));
}

protected final void parse(Class<?> clazz, String beanName) throws IOException {
   processConfigurationClass(new ConfigurationClass(clazz, beanName));
}

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
   processConfigurationClass(new ConfigurationClass(metadata, beanName));
}复制代码

注意!这里有3个parse方法,每个方法里面都执行了下面这个方法;

processConfigurationClass(new ConfigurationClass(metadata, beanName));
复制代码

然后我们继续往下走,在processConfigurationClass(ConfigurationClass configClass)方法内,有一个do循环

do {
   sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}复制代码

我们继续进去看看,这个时候,出现了许多我们常用的注解,Spring会找到这些注解,并对它们进行解析。我们看代码:

for (AnnotationAttributes componentScan : componentScans) {
   // The config class is annotated with @ComponentScan -> perform the scan immediately
   Set<BeanDefinitionHolder> scannedBeanDefinitions =
         this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
   // Check the set of scanned definitions for any further config classes and parse recursively if needed
   for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
      BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
      if (bdCand == null) {
         bdCand = holder.getBeanDefinition();
      }
      if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
         parse(bdCand.getBeanClassName(), holder.getBeanName());
      }
   }
}复制代码
Set<BeanDefinitionHolder> scannedBeanDefinitions =
      this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());复制代码

进入 this.componentScanParser.parse,直接进入结尾的scannner.doScan

return scanner.doScan(StringUtils.toStringArray(basePackages));

然后就会开始扫描basePackages,并将扫描到的bean生成一个一个BeanDefinitionHolder,BeanDefinitionHolder中包含有我们bean的一些相关信息、以及Spring赋予其的额外信息

for (String basePackage : basePackages) {
   Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
   for (BeanDefinition candidate : candidates) {
      ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
      candidate.setScope(scopeMetadata.getScopeName());
      String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
      if (candidate instanceof AbstractBeanDefinition) {
         postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
      }
      if (candidate instanceof AnnotatedBeanDefinition) {
         AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
      }
      if (checkCandidate(beanName, candidate)) {
         BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
         definitionHolder =
               AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
         beanDefinitions.add(definitionHolder);
         registerBeanDefinition(definitionHolder, this.registry);
      }
   }
}复制代码

然后就开始调用如下方法将bean注册到BenFactory中!

 registerBeanDefinition(definitionHolder, this.registry);复制代码

OK,注册完后,invokeBeanFactoryPostProcessors(beanFactory)这个方法也算是使命结束,这个时候我们直接跳到finishBeanFactoryInitialization(beanFactory)这个方法,我们点进去:

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));
   }

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

   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

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

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

   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();
}复制代码

到这个阶段了,我们要开始创建bean的实例了,我们找到下面的代码:

  for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }复制代码

进入getBean!

@Override
public Object getBean(String name) throws BeansException {
   assertBeanFactoryActive();
   return getBeanFactory().getBean(name);
}复制代码

再进getBean

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}复制代码

哎哟,我去,还有一层啊,有点烦!再进去!

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;

   // Eagerly check singleton cache for manually registered singletons.
   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 {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (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);
         }
      }

      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         // Create bean instance.
         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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }

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

         else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, 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;
      }
   }

   // Check if required type matches the type of the actual bean instance.
   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());
      }
   }
   return (T) bean;
}复制代码

然后我们继续哐哐哐往下整吧(任重道远啊!好多层!)

从上面的代码找到这一行,看名字就是创建Bean,我们继续点进去

prototypeInstance = createBean(beanName, mbd, args);复制代码

这个方法进去后,找到下面这行,继续进去(要疯了,兄弟们)

Object beanInstance = doCreateBean(beanName, mbdToUse, args);
复制代码

OKKKKK,这个进去后还有,找到下面代码:

if (instanceWrapper == null) {
   instanceWrapper = createBeanInstance(beanName, mbd, args);
}复制代码

然后再进入createBeanInstance方法,找到下面的代码

if (autowireNecessary) {
   return autowireConstructor(beanName, mbd, null, null);
}复制代码

进入autowireConstructor(很明显,注解构造器),然后.....Emmm....里面还有,我们在里面找到下面这段代码:

if (System.getSecurityManager() != null) {
   final Constructor<?> ctorToUse = constructorToUse;
   final Object[] argumentsToUse = argsToUse;
   beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
      @Override
      public Object run() {
         return beanFactory.getInstantiationStrategy().instantiate(
               mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
      }
   }, beanFactory.getAccessControlContext());
}
else {
   beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
         mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}复制代码

啥也别说了,继续进入这个方法,好像到一个工具类了,看到希望了!!!

@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
      final Constructor<?> ctor, Object... args) {

   if (bd.getMethodOverrides().isEmpty()) {
      if (System.getSecurityManager() != null) {
         // use own privileged to change accessibility (when security is on)
         AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
               ReflectionUtils.makeAccessible(ctor);
               return null;
            }
         });
      }
      return BeanUtils.instantiateClass(ctor, args);
   }
   else {
      return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
   }
}复制代码
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
   Assert.notNull(ctor, "Constructor must not be null");
   try {
      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());
   }
}复制代码
@CallerSensitive
public T newInstance(Object ... initargs)
    throws InstantiationException, IllegalAccessException,
           IllegalArgumentException, InvocationTargetException
{
    if (!override) {
        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            checkAccess(caller, clazz, null, modifiers);
        }
    }
    if ((clazz.getModifiers() & Modifier.ENUM) != 0)
        throw new IllegalArgumentException("Cannot reflectively create enum objects");
    ConstructorAccessor ca = constructorAccessor;   // read volatile
    if (ca == null) {
        ca = acquireConstructorAccessor();
    }
    @SuppressWarnings("unchecked")
    T inst = (T) ca.newInstance(initargs);
    return inst;
}复制代码

感动落泪,终于到了Spring bean加载的核心了!对!反射!我们最后会发现是通过反射newInstance取得的对象实例:

获取到对象实例之后,我们要干啥?填充一波 调用populateBean方法!

try {
   populateBean(beanName, mbd, instanceWrapper);
   if (exposedObject != null) {
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
}复制代码

继续点进去,进入后便能看到和我们平时代码对应的条件了,例如byType注入、byName注入:

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;
}复制代码
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;
         }
      }
   }
}复制代码

这个时候,这一行代码,就是进行依赖注入的地方了!

 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);复制代码

这个时候,我们一点,发现有很多实现类,感觉我们平时项目里面@Autowired注解用得多一点,我们就选AutowiredAnnotationBeanPostProcessor这个类吧,点开看看:

@Override
public PropertyValues postProcessPropertyValues(
      PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

   InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
   try {
      metadata.inject(bean, beanName, pvs);
   }
   catch (BeanCreationException ex) {
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
   }
   return pvs;复制代码

看findAutowiringMetadata这个方法名应该是获取元信息,获取完后,再调用:

 metadata.inject(bean, beanName, pvs);复制代码
@Override
   protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
      Field field = (Field) this.member;
      Object value;
      if (this.cached) {
         value = resolvedCachedArgument(beanName, this.cachedFieldValue);
      }
      else {
         DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
         desc.setContainingClass(bean.getClass());
         Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
         TypeConverter typeConverter = beanFactory.getTypeConverter();
         try {
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
         }
         catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
         }
         synchronized (this) {
            if (!this.cached) {
               if (value != null || this.required) {
                  this.cachedFieldValue = desc;
                  registerDependentBeans(beanName, autowiredBeanNames);
                  if (autowiredBeanNames.size() == 1) {
                     String autowiredBeanName = autowiredBeanNames.iterator().next();
                     if (beanFactory.containsBean(autowiredBeanName)) {
                        if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                           this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                 desc, autowiredBeanName, field.getType());
                        }
                     }
                  }
               }
               else {
                  this.cachedFieldValue = null;
               }
               this.cached = true;
            }
         }
      }
      if (value != null) {
         ReflectionUtils.makeAccessible(field);
         field.set(bean, value);
      }
   }
}复制代码

激动啊,这个莫非就是传说中替我们做的set方法??最后完成注入?

field.set(bean, value);

四、总结

写完这个之后,总体对Spring加载的过程有了更深入的理解,在看源码的过程中,也有很多自己不理解的东西,也综合了很多信息来帮忙自己理解和完成这次文章,相信大哥们看完可能会发现一些错误或者理解不一致处,欢迎指出,共同进步!