SpringBoot启动流程及自动装配原理分析

一、SpringApplication类初始化过程

SpringBoot项目的main函数

常规的这个主类如下图所示,我们一般会这样去写。

在这个类中需要关注的是:

  • @SpringBootApplication
  • SpringApplication.run()

关于 @SpringBootApplication 注解,在后面分析SpringBoot自动装配的章节会展开去分析。

本章节中我们需要关注的就是 SpringApplication.run() 方法。

查看run()方法的实现,如下面代码所示,我们发现其首先是创建了 SpringApplication 的实例,然后调用了 SpringApplication 的run()方法,那本章我们关注的就是 SpringApplication 创建实例的过程。

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return (new SpringApplication(primarySources)).run(args);
}
SpringApplication() 构造方法

继续查看源码, SpringApplication 实例化过程,首先是进入构造方法,最终回来到两个参数的构造方法。

public SpringApplication(Class<?>... primarySources) {
    this((ResourceLoader)null, primarySources);
}

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.sources = new LinkedHashSet();
    this.bannerMode = Mode.CONSOLE;
    this.logStartupInfo = true;
    this.addCommandLineProperties = true;
    this.addConversionService = true;
    this.headless = true;
    this.registerShutdownHook = true;
    this.additionalProfiles = new HashSet();
    this.isCustomEnvironment = false;
    this.lazyInitialization = false;
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    //推断应用类型,后面会根据类型初始化对应的环境。常用的一般都是servlet环境
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //初始化classpath下 META-INF/spring.factories中已配置的ApplicationContextInitializer
    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    //初始化classpath下所有已配置的 ApplicationListener
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    //根据调用栈,推断出 main 方法的类名
    this.mainApplicationClass = this.deduceMainApplicationClass();
}
WebApplicationType.deduceFromClasspath();该方法推断应用的类型。 SERVLET REACTIVE NONE 
public enum WebApplicationType {
    NONE,
    SERVLET,
    REACTIVE;
    
    // 常量值
    private static final String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
    private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
    private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
    private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
    private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
    private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";

    private WebApplicationType() {
    }
    
    /**
     * 判断 应用的类型
     * NONE: 应用程序不是web应用,也不应该用web服务器去启动
     * SERVLET: 应用程序应作为基于servlet的web应用程序运行,并应启动嵌入式servlet web(tomcat)服务器。
     * REACTIVE: 应用程序应作为 reactive web应用程序运行,并应启动嵌入式 reactive web服务器。
     * @return
     */
    static WebApplicationType deduceFromClasspath() {
         //classpath下必须存在org.springframework.web.reactive.DispatcherHandler
        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
            return REACTIVE;
        } else {
            String[] var0 = SERVLET_INDICATOR_CLASSES;
            int var1 = var0.length;

            for(int var2 = 0; var2 < var1; ++var2) {
                String className = var0[var2];
                if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
                    return NONE;
                }
            }
            //classpath环境下存在javax.servlet.Servlet或者org.springframework.web.context.ConfigurableWebApplicationContext
            return SERVLET;
        }
    }

    static WebApplicationType deduceFromApplicationContext(Class<?> applicationContextClass) {
        if (isAssignable("org.springframework.web.context.WebApplicationContext", applicationContextClass)) {
            return SERVLET;
        } else {
            return isAssignable("org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext", applicationContextClass) ? REACTIVE : NONE;
        }
    }

    private static boolean isAssignable(String target, Class<?> type) {
        try {
            return ClassUtils.resolveClassName(target, (ClassLoader)null).isAssignableFrom(type);
        } catch (Throwable var3) {
            return false;
        }
    }
}

返回类型是WebApplicationType的枚举类型, WebApplicationType 有三个枚举,三个枚举的解释如下:

  • WebApplicationType.REACTIVE classpath下存在org.springframework.web.reactive.DispatcherHandler
  • WebApplicationType.SERVLET classpath下存在javax.servlet.Servlet或者org.springframework.web.context.ConfigurableWebApplicationContext
  • WebApplicationType.NONE 不满足以上条件。
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); 

初始化classpath下 META-INF/spring.factories中已配置的ApplicationContextInitializer。

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
    return this.getSpringFactoriesInstances(type, new Class[0]);
}

/**
 * 通过指定的classloader 从META-INF/spring.factories获取指定的Spring的工厂实例
 * @param type
 * @param parameterTypes
 * @param args
 * @param <T>
 * @return
 */
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = this.getClassLoader();
    //通过指定的classLoader从 META-INF/spring.factories 的资源文件中,
    //读取 key 为 type.getName() 的 value
    Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    //创建Spring工厂实例
    List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    //对Spring工厂实例排序(org.springframework.core.annotation.Order注解指定的顺序)
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

看看 getSpringFactoriesInstances 都干了什么,看源码,有一个方法很重要 loadFactoryNames() 这个方法很重要,它是spring-core中提供的从META-INF/spring.factories中获取指定的类(key)的同一入口方法。

在这里,获取的是key为 org.springframework.context.ApplicationContextInitializer 的类。

ApplicationContextInitializer 是Spring框架的类, 这个类的主要目的就是在ConfigurableApplicationContext调用refresh()方法之前,回调这个类的initialize方法。通过ConfigurableApplicationContext 的实例获取容器的环境Environment,从而实现对配置文件的修改完善等工作。

setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

初始化classpath下 META-INF/spring.factories中已配置的 ApplicationListener。
ApplicationListener 的加载过程和上面的 ApplicationContextInitializer 类的加载过程是一样的。不多说了,至于 ApplicationListener 是spring的事件监听器,典型的观察者模式,通过 ApplicationEvent 类和 ApplicationListener 接口,可以实现对spring容器全生命周期的监听,当然也可以自定义监听事件。

二、SpringApplication的run方法

run方法的源码

/**
 * 运行spring应用,并刷新一个新的 ApplicationContext(Spring的上下文)
 * ConfigurableApplicationContext 是 ApplicationContext 接口的子接口。在 ApplicationContext
 * 基础上增加了配置上下文的工具。 ConfigurableApplicationContext是容器的高级接口
 */
public ConfigurableApplicationContext run(String... args) {
    //记录程序运行时间
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    // ConfigurableApplicationContext Spring 的上下文
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    this.configureHeadlessProperty();
    //从META-INF/spring.factories中获取监听器
    //1、获取并启动监听器
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting();

    Collection exceptionReporters;
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //2、构造应用上下文环境
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        //处理需要忽略的Bean
        this.configureIgnoreBeanInfo(environment);
        //打印banner
        Banner printedBanner = this.printBanner(environment);
        //3、初始化应用上下文
        context = this.createApplicationContext();
        //实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
        exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
        //4、刷新应用上下文前的准备阶段
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        //5、刷新应用上下文
        this.refreshContext(context);
        //刷新应用上下文后的扩展接口
        this.afterRefresh(context, applicationArguments);
        //时间记录停止
        stopWatch.stop();
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }
        //发布容器启动完成事件
        listeners.started(context);
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, exceptionReporters, listeners);
        throw new IllegalStateException(var10);
    }

    try {
        listeners.running(context);
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}

具体的每一行代码的含义请看注释,我们在这先总结一下启动过程中的重要步骤:

第一步:获取并启动监听器
第二步:构造应用上下文环境
第三步:初始化应用上下文
第四步:刷新应用上下文前的准备阶段
第五步:刷新应用上下文
第六步:刷新应用上下文后的扩展接口

OK,下面SpringBoot的启动流程分析,我们就根据这6大步骤进行详细解读。最重要的是第四,五步。我们会着重的分析。

第一步:获取并启动监听器

事件机制在Spring是很重要的一部分内容,通过事件机制我们可以监听Spring容器中正在发生的一些事件,同样也可以自定义监听事件。Spring的事件为Bean和Bean之间的消息传递提供支持。当一个对象处理完某种任务后,通知另外的对象进行某些处理,常用的场景有进行某些操作后发送通知,消息、邮件等情况。

private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class<?>[] types = new Class<?>[]{SpringApplication.class, String[].class};
    return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
            SpringApplicationRunListener.class, types, this, args));
}

在这里面是不是看到一个熟悉的方法:getSpringFactoriesInstances(),可以看下下面的注释,前面我们已经详细介绍过该方法是怎么一步步的获取到META-INF/spring.factories中的指定的key的value,获取到以后怎么实例化类的。

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = this.getClassLoader();
    //通过指定的classLoader从 META-INF/spring.factories 的资源文件中,
    //读取 key 为 type.getName() 的 value
    Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    //创建Spring工厂实例
    List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    //对Spring工厂实例排序(org.springframework.core.annotation.Order注解指定的顺序)
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

回到run方法,debug这个代码 SpringApplicationRunListeners listeners = getRunListeners(args); 获取的是EventPublishingRunListener监听器:

EventPublishingRunListener监听器是Spring容器的启动监听器。
listeners.starting(); 开启了监听事件。

第二步:构造应用上下文环境

应用上下文环境包括什么呢?包括计算机的环境,Java环境,Spring的运行环境,Spring项目的配置(在SpringBoot中就是那个熟悉的application.properties/yml)等等。
首先看一下prepareEnvironment()方法。

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    //创建并配置相应的环境
    ConfigurableEnvironment environment = this.getOrCreateEnvironment();
    //根据用户配置,配置 environment系统环境
    this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach((Environment)environment);
    // 启动相应的监听器,其中一个重要的监听器 ConfigFileApplicationListener 就是加载项目配置文件的监听器。
    listeners.environmentPrepared((ConfigurableEnvironment)environment);
    this.bindToSpringApplication((ConfigurableEnvironment)environment);
    if (!this.isCustomEnvironment) {
        environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
    }

    ConfigurationPropertySources.attach((Environment)environment);
    return (ConfigurableEnvironment)environment;
}

看上面的注释,方法中主要完成的工作,首先是创建并按照相应的应用类型配置相应的环境,然后根据用户的配置,配置系统环境,然后启动监听器,并加载系统配置文件。

ConfigurableEnvironment environment = getOrCreateEnvironment(); 
private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    } else {
        switch(this.webApplicationType) {
        case SERVLET:
            //如果应用类型是 SERVLET 则实例化 StandardServletEnvironment
            return new StandardServletEnvironment();
        case REACTIVE:
            return new StandardReactiveWebEnvironment();
        default:
            return new StandardEnvironment();
        }
    }
}

通过代码可以看到根据不同的应用类型初始化不同的系统环境实例。前面咱们已经说过应用类型是怎么判断的了,这里就不在赘述了。

从上面的继承关系可以看出,StandardServletEnvironment是StandardEnvironment的子类。当是web项目的时候,环境上会多一些关于web环境的配置。 

configureEnvironment(environment, applicationArguments.getSourceArgs()); 
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    if (this.addConversionService) {
        ConversionService conversionService = ApplicationConversionService.getSharedInstance();
        environment.setConversionService((ConfigurableConversionService)conversionService);
    }
    // 将main 函数的args封装成 SimpleCommandLinePropertySource 加入环境中。
    this.configurePropertySources(environment, args);
     // 激活相应的配置文件
    this.configureProfiles(environment, args);
}

在configurePropertySources(environment, args);中将args封装成了SimpleCommandLinePropertySource并加入到了environment中。

configureProfiles(environment, args);根据启动参数激活了相应的配置文件。

 listeners.environmentPrepared(environment); 

进入到方法一路跟下去就到了SimpleApplicationEventMulticaster类的multicastEvent()方法。

public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
    Executor executor = this.getTaskExecutor();
    Iterator var5 = this.getApplicationListeners(event, type).iterator();

    while(var5.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var5.next();
        if (executor != null) {
            executor.execute(() -> {
                this.invokeListener(listener, event);
            });
        } else {
            this.invokeListener(listener, event);
        }
    }

}

查看getApplicationListeners(event, type)执行结果,发现一个重要的监听器ConfigFileApplicationListener。

先看看这个类的注释:

/**
 * {@link EnvironmentPostProcessor} that configures the context environment by loading
 * properties from well known file locations. By default properties will be loaded from
 * 'application.properties' and/or 'application.yml' files in the following locations:
 * <ul>
 * <li>classpath:</li>
 * <li>file:./</li>
 * <li>classpath:config/</li>
 * <li>file:./config/:</li>
 * </ul>
 * <p>
 * Alternative search locations and names can be specified using
 * {@link #setSearchLocations(String)} and {@link #setSearchNames(String)}.
 * <p>
 * Additional files will also be loaded based on active profiles. For example if a 'web'
 * profile is active 'application-web.properties' and 'application-web.yml' will be
 * considered.
 * <p>
 * The 'spring.config.name' property can be used to specify an alternative name to load
 * and the 'spring.config.location' property can be used to specify alternative search
 * locations or specific files.
 * <p>
 * 从默认的位置加载配置文件,并将其加入 上下文的 environment变量中
 */

这个监听器默认的从注释中<ul>标签所示的几个位置加载配置文件,并将其加入 上下文的 environment变量中。当然也可以通过配置指定。

第三步:初始化应用上下文

在SpringBoot工程中,应用类型分为三种,如下代码所示。

public enum WebApplicationType {
    /**
     * 应用程序不是web应用,也不应该用web服务器去启动
     */
    NONE,
    /**
     * 应用程序应作为基于servlet的web应用程序运行,并应启动嵌入式servlet web(tomcat)服务器。
     */
    SERVLET,
    /**
     * 应用程序应作为 reactive web应用程序运行,并应启动嵌入式 reactive web服务器。
     */
    REACTIVE
}

对应三种应用类型,SpringBoot项目有三种对应的应用上下文,我们以web工程为例,即其上下文为AnnotationConfigServletWebServerApplicationContext。

 protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch(this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                    break;
                case REACTIVE:
                    contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                    break;
                default:
                    contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
                }
            } catch (ClassNotFoundException var3) {
                throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
            }
        }

        return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
    }

我们先看一下AnnotationConfigServletWebServerApplicationContext的设计。

应用上下文可以理解成IoC容器的高级表现形式,应用上下文确实是在IoC容器的基础上丰富了一些高级功能。
应用上下文对IoC容器是持有的关系。它的一个属性beanFactory就是IoC容器(DefaultListableBeanFactory)。所以它们之间是持有,和扩展的关系。

接下来看GenericApplicationContext类

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    private final DefaultListableBeanFactory beanFactory;
    ...
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
    ...
}

beanFactory正是在AnnotationConfigServletWebServerApplicationContext实现的接口GenericApplicationContext中定义的。在上面createApplicationContext()方法中的, BeanUtils.instantiateClass(contextClass) 这个方法中,不但初始化了AnnotationConfigServletWebServerApplicationContext类,也就是我们的上下文context,同样也触发了GenericApplicationContext类的构造函数,从而IoC容器也创建了。仔细看他的构造函数,有没有发现一个很熟悉的类DefaultListableBeanFactory,没错,DefaultListableBeanFactory就是IoC容器真实面目了。在后面的refresh()方法分析中,DefaultListableBeanFactory是无处不在的存在感。

第四步 刷新应用上下文前的准备阶段
prepareContext()方法
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    //设置容器环境
    context.setEnvironment(environment);
    //执行容器后置处理
    this.postProcessApplicationContext(context);
    //执行容器中的 ApplicationContextInitializer 包括spring.factories和通过三种方式自定义的
    this.applyInitializers(context);
    //向各个监听器发送容器已经准备好的事件
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
        this.logStartupInfo(context.getParent() == null);
        this.logStartupProfileInfo(context);
    }

    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    //将main函数中的args参数封装成单例Bean,注册进容器
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    //将 printedBanner 也封装成单例,注册进容器
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }

    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }

    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }

    Set<Object> sources = this.getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    //加载我们的启动类,将启动类注入容器
    this.load(context, sources.toArray(new Object[0]));
    //发布容器已加载事件
    listeners.contextLoaded(context);
}

首先看这行 Set<Object> sources = getAllSources(); 在getAllSources()中拿到了我们的启动类。  
我们重点讲解这行 load(context, sources.toArray(new Object[0]));

跟进load()方法,看源码:

protected void load(ApplicationContext context, Object[] sources) {
    if (logger.isDebugEnabled()) {
        logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
    }
    //创建 BeanDefinitionLoader 
    BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);
    if (this.beanNameGenerator != null) {
        loader.setBeanNameGenerator(this.beanNameGenerator);
    }

    if (this.resourceLoader != null) {
        loader.setResourceLoader(this.resourceLoader);
    }

    if (this.environment != null) {
        loader.setEnvironment(this.environment);
    }

    loader.load();
}

1、getBeanDefinitionRegistry()

继续看getBeanDefinitionRegistry()方法的源码

private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
    if (context instanceof BeanDefinitionRegistry) {
        return (BeanDefinitionRegistry)context;
    } else if (context instanceof AbstractApplicationContext) {
        return (BeanDefinitionRegistry)((AbstractApplicationContext)context).getBeanFactory();
    } else {
        throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
    }
}

这里将我们前文创建的上下文强转为BeanDefinitionRegistry,是不是很熟悉。BeanDefinitionRegistry定义了很重要的方法registerBeanDefinition(),该方法将BeanDefinition注册进DefaultListableBeanFactory容器的beanDefinitionMap中。

2、createBeanDefinitionLoader()

继续看createBeanDefinitionLoader()方法,最终进入了BeanDefinitionLoader类的构造方法,如下

BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
    Assert.notNull(registry, "Registry must not be null");
    Assert.notEmpty(sources, "Sources must not be empty");
    this.sources = sources;
    //注解形式的Bean定义读取器 比如:@Configuration @Bean @Component @Controller @Service等等
    this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
    //XML形式的Bean定义读取器
    this.xmlReader = new XmlBeanDefinitionReader(registry);
    if (this.isGroovyPresent()) {
        this.groovyReader = new GroovyBeanDefinitionReader(registry);
    }
    //类路径扫描器
    this.scanner = new ClassPathBeanDefinitionScanner(registry);
    //扫描器添加排除过滤器
    this.scanner.addExcludeFilter(new BeanDefinitionLoader.ClassExcludeFilter(sources));
}

前面的文章,我们说过,IoC容器的初始化分为三个步骤,上面三个属性在,BeanDefinition的Resource定位,和BeanDefinition的注册中起到了很重要的作用。

3、loader.load();

跟进load()方法

private int load(Object source) {
    Assert.notNull(source, "Source must not be null");
    if (source instanceof Class) {
        // 从Class加载
        return this.load((Class)source);
    } else if (source instanceof Resource) {
        // 从Resource加载
        return this.load((Resource)source);
    } else if (source instanceof Package) {
        // 从Package加载
        return this.load((Package)source);
    } else if (source instanceof CharSequence) {
        // 从 CharSequence 加载
        return this.load((CharSequence)source);
    } else {
        throw new IllegalArgumentException("Invalid source type " + source.getClass());
    }
}

当前我们的主类会按Class加载。

继续跟进load()方法。

private int load(Class<?> source) {
    if (this.isGroovyPresent() && BeanDefinitionLoader.GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
        BeanDefinitionLoader.GroovyBeanDefinitionSource loader = (BeanDefinitionLoader.GroovyBeanDefinitionSource)BeanUtils.instantiateClass(source, BeanDefinitionLoader.GroovyBeanDefinitionSource.class);
        this.load(loader);
    }

    if (this.isEligible(source)) {
        //将 启动类的 BeanDefinition注册进 beanDefinitionMap
        this.annotatedReader.register(new Class[]{source});
        return 1;
    } else {
        return 0;
    }
}

isComponent(source)判断主类是不是存在@Component注解,主类@SpringBootApplication是一个组合注解,包含@Component。

this.annotatedReader.register(source);跟进register()方法,最终进到AnnotatedBeanDefinitionReader类的doRegisterBean()方法。

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
    //将指定的类 封装为AnnotatedGenericBeanDefinition
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        abd.setInstanceSupplier(supplier);
        // 获取该类的 scope 属性
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        int var10;
        int var11;
        if (qualifiers != null) {
            Class[] var9 = qualifiers;
            var10 = qualifiers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                Class<? extends Annotation> qualifier = var9[var11];
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                } else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                } else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        if (customizers != null) {
            BeanDefinitionCustomizer[] var13 = customizers;
            var10 = customizers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                BeanDefinitionCustomizer customizer = var13[var11];
                customizer.customize(abd);
            }
        }

        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        // 将该BeanDefinition注册到IoC容器的beanDefinitionMap中
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}

在该方法中将主类封装成AnnotatedGenericBeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);方法将BeanDefinition注册进beanDefinitionMap

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    // 注册别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        String[] var4 = aliases;
        int var5 = aliases.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String alias = var4[var6];
            registry.registerAlias(beanName, alias);
        }
    }

}

继续跟进registerBeanDefinition()方法。

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            // 最后一次校验了
            // 对bean的Overrides进行校验,还不知道会在哪处理这些overrides
            ((AbstractBeanDefinition)beanDefinition).validate();
        } catch (BeanDefinitionValidationException var8) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
        }
    }
    // 判断是否存在重复名字的bean,之后看允不允许override
    // 以前使用synchronized实现互斥访问,现在采用ConcurrentHashMap
    BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
         //如果该类不允许 Overriding 直接抛出异常
        if (!this.isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }

        if (existingDefinition.getRole() < beanDefinition.getRole()) {
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (!beanDefinition.equals(existingDefinition)) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
        }
        //注册进beanDefinitionMap
        this.beanDefinitionMap.put(beanName, beanDefinition);
    } else {
        if (this.hasBeanCreationStarted()) {
            synchronized(this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                this.removeManualSingletonName(beanName);
            }
        } else {
            //如果仍处于启动注册阶段,注册进beanDefinitionMap
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.removeManualSingletonName(beanName);
        }

        this.frozenBeanDefinitionNames = null;
    }

    if (existingDefinition == null && !this.containsSingleton(beanName)) {
        if (this.isConfigurationFrozen()) {
            this.clearByTypeCache();
        }
    } else {
        this.resetBeanDefinition(beanName);
    }

}

最终来到DefaultListableBeanFactory类的registerBeanDefinition()方法,DefaultListableBeanFactory类还熟悉吗?DefaultListableBeanFactory是IoC容器的具体产品。
仔细看这个方法registerBeanDefinition(),首先会检查是否已经存在,如果存在并且不允许被覆盖则直接抛出异常。不存在的话就直接注册进beanDefinitionMap中。

第五步 刷新应用上下文(IoC容器的初始化过程)

IoC容器的初始化过程,主要分下面三步:

  • BeanDefinition的Resource定位
  • BeanDefinition的载入
  • 向IoC容器注册BeanDefinition

从run方法的,refreshContext()方法一路跟下去,最终来到AbstractApplicationContext类的refresh()方法。

public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
         //刷新上下文环境
        this.prepareRefresh();
        //这里是在子类中启动 refreshBeanFactory() 的地方
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        //准备bean工厂,以便在此上下文中使用
        this.prepareBeanFactory(beanFactory);

        try {
            //设置 beanFactory 的后置处理
            this.postProcessBeanFactory(beanFactory);
            //调用 BeanFactory 的后处理器,这些处理器是在Bean 定义中向容器注册的
            this.invokeBeanFactoryPostProcessors(beanFactory);
            //注册Bean的后处理器,在Bean创建过程中调用
            this.registerBeanPostProcessors(beanFactory);
            //对上下文中的消息源进行初始化
            this.initMessageSource();
            //初始化上下文中的事件机制
            this.initApplicationEventMulticaster();
            //初始化其他特殊的Bean
            this.onRefresh();
            //检查监听Bean并且将这些监听Bean向容器注册
            this.registerListeners();
            //实例化所有的(non-lazy-init)单件
            this.finishBeanFactoryInitialization(beanFactory);
            //发布容器事件,结束Refresh过程
            this.finishRefresh();
        } catch (BeansException var9) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
            }

            this.destroyBeans();
            this.cancelRefresh(var9);
            throw var9;
        } finally {
            this.resetCommonCaches();
        }

    }
}

从以上代码中我们可以看到,refresh()方法中所作的工作也挺多,我们没办法面面俱到,主要根据IoC容器的初始化步骤和IoC依赖注入的过程进行分析,围绕以上两个过程,我们主要介绍重要的方法。

obtainFreshBeanFactory();

在启动流程的第三步:初始化应用上下文。中我们创建了应用的上下文,并触发了GenericApplicationContext类的构造方法如下所示,创建了beanFactory,也就是创建了DefaultListableBeanFactory类。

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

关于obtainFreshBeanFactory()方法,其实就是拿到我们之前创建的beanFactory。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //刷新BeanFactory
    this.refreshBeanFactory();
    //获取beanFactory
    return this.getBeanFactory();
}

从上面代码可知,在该方法中主要做了三个工作,刷新beanFactory,获取beanFactory,返回beanFactory。
首先看一下refreshBeanFactory()方法,跟下去来到GenericApplicationContext类的refreshBeanFactory()发现也没做什么。

protected final void refreshBeanFactory() throws IllegalStateException {
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    } else {
        this.beanFactory.setSerializationId(this.getId());
    }
}

AbstractApplicationContext类有两个子类实现了refreshBeanFactory(),但是在前面第三步初始化上下文的时候,实例化了GenericApplicationContext类,所以没有进入AbstractRefreshableApplicationContext中的refreshBeanFactory()方法。

this.refreshed.compareAndSet(false, true) ,这行代码在这里表示:GenericApplicationContext只允许刷新一次 。这行代码,很重要,不是在Spring中很重要,而是这行代码本身。首先看一下this.refreshed属性: 

private final AtomicBoolean refreshed = new AtomicBoolean();

java J.U.C并发包中很重要的一个原子类AtomicBoolean。通过该类的compareAndSet()方法可以实现一段代码绝对只实现一次的功能。

prepareBeanFactory(beanFactory);

从字面意思上可以看出准备BeanFactory。
看代码,具体看看做了哪些准备工作。这个方法不是重点,看注释吧。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 配置类加载器:默认使用当前上下文的类加载器
    beanFactory.setBeanClassLoader(this.getClassLoader());
    // 配置EL表达式:在Bean初始化完成,填充属性的时候会用到
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 添加属性编辑器 PropertyEditor
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
    // 添加Bean的后置处理器
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 忽略装配以下指定的类
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
     // 将以下类注册到 beanFactory(DefaultListableBeanFactory) 的resolvableDependencies属性中
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    // 将早期后处理器注册为application监听器,用于检测内部bean
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    // 如果当前BeanFactory包含loadTimeWeaver Bean,说明存在类加载期织入AspectJ,
    // 则把当前BeanFactory交给类加载期BeanPostProcessor实现类LoadTimeWeaverAwareProcessor来处理,
    // 从而实现类加载期织入AspectJ的目的。
    if (beanFactory.containsBean("loadTimeWeaver")) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // 将当前环境变量(environment) 注册为单例bean
    if (!beanFactory.containsLocalBean("environment")) {
        beanFactory.registerSingleton("environment", this.getEnvironment());
    }
    // 将当前系统配置(systemProperties) 注册为单例Bean
    if (!beanFactory.containsLocalBean("systemProperties")) {
        beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
    }
    // 将当前系统环境 (systemEnvironment) 注册为单例Bean
    if (!beanFactory.containsLocalBean("systemEnvironment")) {
        beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
    }

}
postProcessBeanFactory(beanFactory);

postProcessBeanFactory()方法向上下文中添加了一系列的Bean的后置处理器。后置处理器工作的时机是在所有的beanDenifition加载完成之后,bean实例化之前执行。简单来说Bean的后置处理器可以修改BeanDefinition的属性信息。

invokeBeanFactoryPostProcessors(beanFactory);(重点)

上面说过,IoC容器的初始化过程包括三个步骤,在invokeBeanFactoryPostProcessors()方法中完成了IoC容器初始化过程的三个步骤。

第一步:Resource定位

在SpringBoot中,我们都知道他的包扫描是从主类所在的包开始扫描的,prepareContext()方法中,会先将主类解析成BeanDefinition,然后在refresh()方法的invokeBeanFactoryPostProcessors()方法中解析主类的BeanDefinition获取basePackage的路径。这样就完成了定位的过程。其次SpringBoot的各种starter是通过SPI扩展机制实现的自动装配,SpringBoot的自动装配同样也是在invokeBeanFactoryPostProcessors()方法中实现的。还有一种情况,在SpringBoot中有很多的@EnableXXX注解,细心点进去看的应该就知道其底层是@Import注解,在invokeBeanFactoryPostProcessors()方法中也实现了对该注解指定的配置类的定位加载。

常规的在SpringBoot中有三种实现定位,第一个是主类所在包的,第二个是SPI扩展机制实现的自动装配(比如各种starter),第三种就是@Import注解指定的类。

第二步:BeanDefinition的载入

第一步中说了三种Resource的定位情况,定位后紧接着就是BeanDefinition的分别载入。所谓的载入就是通过上面的定位得到的basePackage,SpringBoot会将该路径拼接成:classpath*:org/springframework/boot/demo/**/*.class这样的形式,然后一个叫做PathMatchingResourcePatternResolver的类会将该路径下所有的.class文件都加载进来,然后遍历判断是不是有@Component注解,如果有的话,就是我们要装载的BeanDefinition。大致过程就是这样的了。 

注:@Configuration,@Controller,@Service等注解底层都是@Component注解,只不过包装了一层罢了。

第三个过程:注册BeanDefinition

这个过程通过调用上文提到的BeanDefinitionRegister接口的实现来完成。这个注册过程把载入过程中解析得到的BeanDefinition向IoC容器进行注册。通过上文的分析,我们可以看到,在IoC容器中将BeanDefinition注入到一个ConcurrentHashMap中,IoC容器就是通过这个HashMap来持有这些BeanDefinition数据的。比如DefaultListableBeanFactory 中的beanDefinitionMap属性。

OK,总结完了,接下来我们通过代码看看具体是怎么实现的。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    ...
}
// PostProcessorRegistrationDelegate类
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    ...
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    ...
}
// PostProcessorRegistrationDelegate类
private static void invokeBeanDefinitionRegistryPostProcessors(
        Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}
// ConfigurationClassPostProcessor类
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    ...
    processConfigBeanDefinitions(registry);
}
// ConfigurationClassPostProcessor类
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    ...
    do {
        parser.parse(candidates);
        parser.validate();
        ...
    }
    ...
}

一路跟踪调用栈,来到ConfigurationClassParser类的parse()方法。

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    Iterator var2 = configCandidates.iterator();

    while(var2.hasNext()) {
        BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
        BeanDefinition bd = holder.getBeanDefinition();

        try {
            // 如果是SpringBoot项目进来的,bd其实就是前面主类封装成的 AnnotatedGenericBeanDefinition(AnnotatedBeanDefinition接口的实现类)
            if (bd instanceof AnnotatedBeanDefinition) {
                this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
            } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
            } else {
                this.parse(bd.getBeanClassName(), holder.getBeanName());
            }
        } catch (BeanDefinitionStoreException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
        }
    }
    // 加载默认的配置---》(对springboot项目来说这里就是自动装配的入口了)
    this.deferredImportSelectorHandler.process();
}

看上面的注释,在前面的prepareContext()方法中,我们详细介绍了我们的主类是如何一步步的封装成AnnotatedGenericBeanDefinition,并注册进IoC容器的beanDefinitionMap中的。

继续沿着parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());方法跟下去

// ConfigurationClassParser类
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
// ConfigurationClassParser类
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
    ...
    // Recursively process the configuration class and its superclass hierarchy.
    //递归地处理配置类及其父类层次结构。
    SourceClass sourceClass = asSourceClass(configClass);
    do {
        //递归处理Bean,如果有父类,递归处理,直到顶层父类
        sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
    while (sourceClass != null);

    this.configurationClasses.put(configClass, configClass);
}
// ConfigurationClassParser类
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
        throws IOException {

    // Recursively process any member (nested) classes first
    //首先递归处理内部类,(SpringBoot项目的主类一般没有内部类)
    processMemberClasses(configClass, sourceClass);

    // Process any @PropertySource annotations
    // 针对 @PropertySource 注解的属性配置处理
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), PropertySources.class,
            org.springframework.context.annotation.PropertySource.class)) {
        if (this.environment instanceof ConfigurableEnvironment) {
            processPropertySource(propertySource);
        } else {
            logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // Process any @ComponentScan annotations
    // 根据 @ComponentScan 注解,扫描项目中的Bean(SpringBoot 启动类上有该注解)
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            // The config class is annotated with @ComponentScan -> perform the scan immediately
            // 立即执行扫描,(SpringBoot项目为什么是从主类所在的包扫描,这就是关键了)
            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();
                }
                // 检查是否是ConfigurationClass(是否有configuration/component两个注解),如果是,递归查找该类相关联的配置类。
                // 所谓相关的配置类,比如@Configuration中的@Bean定义的bean。或者在有@Component注解的类上继续存在@Import注解。
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

    // Process any @Import annotations
    //递归处理 @Import 注解(SpringBoot项目中经常用的各种@Enable*** 注解基本都是封装的@Import)
    processImports(configClass, sourceClass, getImports(sourceClass), true);

    // Process any @ImportResource annotations
    AnnotationAttributes importResource =
            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        String[] resources = importResource.getStringArray("locations");
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // Process individual @Bean methods
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // Process default methods on interfaces
    processInterfaces(configClass, sourceClass);

    // Process superclass, if any
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        if (superclass != null && !superclass.startsWith("java") &&
                !this.knownSuperclasses.containsKey(superclass)) {
            this.knownSuperclasses.put(superclass, configClass);
            // Superclass found, return its annotation metadata and recurse
            return sourceClass.getSuperClass();
        }
    }

    // No superclass -> processing is complete
    return null;
}

看doProcessConfigurationClass()方法。(SpringBoot的包扫描的入口方法,重点哦)

for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(... 获取主类上的@PropertySource注解(关于该注解是怎么用的请自行百度),解析该注解并将该注解指定的properties配置文件中的值存储到Spring的 Environment中,Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。

Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); 解析主类上的@ComponentScan注解,呃,怎么说呢,42行后面的代码将会解析该注解并进行包扫描。

processImports(configClass, sourceClass, getImports(sourceClass), true); 解析主类上的@Import注解,并加载该注解指定的配置类。

提示:在spring中好多注解都是一层一层封装的,比如@EnableXXX,是对@Import注解的二次封装。@SpringBootApplication注解=@ComponentScan+@EnableAutoConfiguration+@Import+@Configuration+@Component。@Controller,@Service等等是对@Component的二次封装。

Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); 进入该方法

// ComponentScanAnnotationParser类
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
            componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    ...
    // 根据 declaringClass (如果是SpringBoot项目,则参数为主类的全路径名)
    if (basePackages.isEmpty()) {
        basePackages.add(ClassUtils.getPackageName(declaringClass));
    }
    ...
    // 根据basePackages扫描类
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}

发现有两行重要的代码。

到这里呢IoC容器初始化三个步骤的第一步,Resource定位就完成了,成功定位到了主类所在的包。

接着往下看 return scanner.doScan(StringUtils.toStringArray(basePackages)); Spring是如何进行类扫描的。进入doScan()方法。

// ComponentScanAnnotationParser类
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
        // 从指定的包中扫描需要装载的Bean
        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);
                //将该 Bean 注册进 IoC容器(beanDefinitionMap)
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

这个方法中有两个比较重要的方法,Set<BeanDefinition> candidates = findCandidateComponents(basePackage); 从basePackage中扫描类并解析成BeanDefinition,拿到所有符合条件的类后在 registerBeanDefinition(definitionHolder, this.registry); 将该类注册进IoC容器。也就是说在这个方法中完成了IoC容器初始化过程的第二三步,BeanDefinition的载入,和BeanDefinition的注册。

findCandidateComponents(basePackage);
// ClassPathScanningCandidateComponentProvider类
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    ...
    else {
        return scanCandidateComponents(basePackage);
    }
}
// ClassPathScanningCandidateComponentProvider类
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
        //拼接扫描路径,比如:classpath*:org/springframework/boot/demo/**/*.class
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        //从 packageSearchPath 路径中扫描所有的类
        Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
        boolean traceEnabled = logger.isTraceEnabled();
        boolean debugEnabled = logger.isDebugEnabled();
        for (Resource resource : resources) {
            if (traceEnabled) {
                logger.trace("Scanning " + resource);
            }
            if (resource.isReadable()) {
                try {
                    MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                    // //判断该类是不是 @Component 注解标注的类,并且不是需要排除掉的类
                    if (isCandidateComponent(metadataReader)) {
                        //将该类封装成 ScannedGenericBeanDefinition(BeanDefinition接口的实现类)类
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        if (isCandidateComponent(sbd)) {
                            if (debugEnabled) {
                                logger.debug("Identified candidate component class: " + resource);
                            }
                            candidates.add(sbd);
                        } else {
                            if (debugEnabled) {
                                logger.debug("Ignored because not a concrete top-level class: " + resource);
                            }
                        }
                    } else {
                        if (traceEnabled) {
                            logger.trace("Ignored because not matching any filter: " + resource);
                        }
                    }
                } catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to read candidate component class: " + resource, ex);
                }
            } else {
                if (traceEnabled) {
                    logger.trace("Ignored because not readable: " + resource);
                }
            }
        }
    } catch (IOException ex) {
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    return candidates;
}

将basePackage拼接成classpath*:org/springframework/boot/demo/**/*.class,在getResources(packageSearchPath);方法中扫描到了该路径下的所有的类。然后遍历这些Resources,在isCandidateComponent(metadataReader)方法中判断该类是不是 @Component 注解标注的类,并且不是需要排除掉的类。ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);将扫描到的类,解析成ScannedGenericBeanDefinition,该类是BeanDefinition接口的实现类。OK,IoC容器的BeanDefinition载入到这里就结束了。

registerBeanDefinition(definitionHolder, this.registry);

查看registerBeanDefinition()方法。是不是有点眼熟,在前面介绍prepareContext()方法时,我们详细介绍了主类的BeanDefinition是怎么一步一步的注册进DefaultListableBeanFactory的beanDefinitionMap中的。在此呢我们就省略1w字吧。完成了BeanDefinition的注册,就完成了IoC容器的初始化过程。此时,在使用的IoC容器DefaultListableFactory中已经建立了整个Bean的配置信息,而这些BeanDefinition已经可以被容器使用了。他们都在BeanbefinitionMap里被检索和使用。容器的作用就是对这些信息进行处理和维护。这些信息是容器简历依赖反转的基础。

protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}

OK,到这里IoC容器的初始化过程的三个步骤就梳理完了。当然这只是针对SpringBoot的包扫描的定位方式的BeanDefinition的定位,加载,和注册过程。前面我们说过,还有两种方式@Import和SPI扩展实现的starter的自动装配。

@Import注解的解析过程

相信不说大家也应该知道了,各种@EnableXXX注解,很大一部分都是对@Import的二次封装(其实也是为了解耦,比如当@Import导入的类发生变化时,我们的业务系统也不需要改任何代码)。

我们又要回到上文中的ConfigurationClassParser类的doProcessConfigurationClass方法的processImports(configClass, sourceClass, getImports(sourceClass), true);

processImports(configClass, sourceClass, getImports(sourceClass), true);中configClass和sourceClass参数都是主类相对应的。

首先看getImports(sourceClass);

private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
    Set<SourceClass> imports = new LinkedHashSet<>();
    Set<SourceClass> visited = new LinkedHashSet<>();
    collectImports(sourceClass, imports, visited);
    return imports;
}

三、SpringBoot自动装配原理实现

通过分析refresh()方法中的invokeBeanFactoryPostProcessors()方法,分析了IoC容器的初始化过程,这一节从代码上如下所示,接上一节ConfigurationClassParser类中的parse()方法,接着分析SpringBoot的自动装配原理。

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    Iterator var2 = configCandidates.iterator();

    while(var2.hasNext()) {
        BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
        BeanDefinition bd = holder.getBeanDefinition();

        try {
            // 如果是SpringBoot项目进来的,bd其实就是前面主类封装成的 AnnotatedGenericBeanDefinition(AnnotatedBeanDefinition接口的实现类)
            if (bd instanceof AnnotatedBeanDefinition) {
                this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
            } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
            } else {
                this.parse(bd.getBeanClassName(), holder.getBeanName());
            }
        } catch (BeanDefinitionStoreException var6) {
            throw var6;
        } catch (Throwable var7) {
            throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
        }
    }
    // 加载默认的配置---》(对springboot项目来说这里就是自动装配的入口了)
    this.deferredImportSelectorHandler.process();
}
@SpringBootApplication注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    ...
}

接着看@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

OK,看到@Import(AutoConfigurationImportSelector.class)导入了一个重要的类AutoConfigurationImportSelector。

AutoConfigurationImportSelector
//自动装配
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    } else {
        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
}

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    } else {
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        //获取所有的自动配置类(META-INF/spring.factories中配置的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的类)
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        configurations = this.removeDuplicates(configurations);
        //需要排除的自动装配类(springboot的主类上 @SpringBootApplication(exclude = {com.demo.starter.config.DemoConfig.class})指定的排除的自动装配类)
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        this.checkExcludedClasses(configurations, exclusions);
        //将需要排除的类从 configurations remove掉
        configurations.removeAll(exclusions);
        configurations = this.getConfigurationClassFilter().filter(configurations);
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
    }
}

至于怎么从章节一中提到的ConfigurationClassParser类中的parse()===>deferredImportSelectorHandler.process();==>AutoConfigurationImportSelector#selectImports(),篇幅有限不做过多介绍。

我们来看一下getCandidateConfigurations()方法是怎么拿到这些自动配置类的。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

是不是又看到一个十分熟悉的方法loadFactoryNames(),没错,其实我们在分析SpringBoot启动流程的的时候,就已经分析了,SpringBoot是如何从META-INF/spring.factories中加载指定key的value的。

继续看Set<String> exclusions = getExclusions(annotationMetadata, attributes);方法,该方法是排除主类上@SpringBootApplication注解上排除的自动装配的类。

configurations = this.getConfigurationClassFilter().filter(configurations);该行代码将会过滤掉不需要装配的类。过滤的逻辑有很多,比如我们常用的@ConditionXXX注解。如下所示:

@ConditionalOnBean:容器中有指定的Bean
@ConditionalOnClass:当类路径下有指定的类
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean:当容器中没有指定Bean的情况下
@ConditionalOnMissingClass:当类路径下没有指定的类
@ConditionalOnNotWebApplication:当前项目不是Web项目
@ConditionalOnProperty:配置文件中指定的属性是否有指定的值
@ConditionalOnResource:类路径下是否有指定的资源
@ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean
@ConditionalOnWebApplication:当前项目是Web项目的条件下 

四、IOC容器依赖注入

前面在refresh()-->invokeBeanFactoryPostProcessors(beanFactory);方法中已经完成了IoC容器的初始化并已经载入了我们定义的Bean的信息(BeanDefinition),现在我们开始分析依赖注入的原理。首先需要说明的是依赖注入在用户第一次向IoC容器索要Bean时触发,当然也有例外,我们可以在BeanDefinition中中通过控制lazy-init属性来让容器完成对Bean的预实例化。这个预实例化实际上也是一个依赖注入的过程,但它是在初始化过程中完成的。

getBean()的过程
// AbstractApplicationContext类
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        ...
        try {
            ...
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
            ...
        }
        ...
    }
}
// AbstractApplicationContext类
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    ...
    // Instantiate all remaining (non-lazy-init) singletons.
    // 实例化所有剩余的(non-lazy-init)单例。
    beanFactory.preInstantiateSingletons();
}
// DefaultListableBeanFactory类
@Override
public void preInstantiateSingletons() throws BeansException {
    ...
    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        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 {
                // 这里就是触发依赖注入的地方
                getBean(beanName);
            }
        }
    }
    ...
}

跟踪其调用栈,看到getBean(beanName);方法,我们再梳理一下getBean()方法,前面总结过该方法在IoC容器的顶层接口BeanFactory中定义,然后在IoC容器的具体产品DefaultListableBeanFactory类的基类AbstractBeanFactory实现了getBean()方法。接着看代码。

// AbstractBeanFactory类
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
    return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
    return doGetBean(name, null, args, false);
}
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
        throws BeansException {
    return doGetBean(name, requiredType, args, false);
}

从上面代码可知大致可分为两种获取Bean的参数,一种是按名获取,一种是按类获取。但是最终都进入到了doGetBean()方法。

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

    // bean获取过程:先获取bean名字
    // 会把带有&前缀的去掉,或者去aliasMap中找这个是不是别名,最终确定bean的id是什么
    final String beanName = transformedBeanName(name);
    Object bean;

    // 1.检查缓存中或者实例工厂中是否有对应的实例
    // 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
    // Spring在创建bean的时候不会等bean创建完成就会将bean的ObjectFactory提早曝光
    // 也就是将ObjectFactory加入到缓存中,一旦下一个要创建的bean需要依赖上个bean则直接使用ObjectFactory
    // 2.spring 默认是单例的,如果能获取到直接返回,提高效率。
    // 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的正确性,同时如果获取的是FactoryBean的话还需要调用getObject()方法获取最终的那个bean实例
        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.
        //这里对IoC容器中的BeanDefinition是否存在进行检查,检查是否能在当前的BeanFactory中取得需要的Bean。
        // 如果当前的工厂中取不到,则到双亲BeanFactory中去取。如果当前的双亲工厂取不到,那就顺着双亲BeanFactory
        // 链一直向上查找。
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                // 递归调用父bean的doGetBean查找
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

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

        try {
            //这里根据Bean的名字取得BeanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            //获取当前Bean的所有依赖Bean,这里会触发getBean的递归调用。知道取到一个没有任何依赖的Bean为止。
            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);
                    }
                }
            }

            // 这里通过createBean方法创建singleton Bean的实例 这里还有一个回调函数
            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        // 最后在getSingleton中又会调用这个方法
                        // TODO createBean的入口
                        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);
            }
            // 这里是创建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);
            }

            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    //这里对创建的Bean进行类型检查,如果没有问题,就返回这个新创建的Bean,这个Bean已经是包含了依赖关系的Bean
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

这个就是依赖注入的入口了,依赖注入是在容器的BeanDefinition数据已经建立好的前提下进行的。“程序=数据+算法”,很经典的一句话,前面我们详细介绍了BeanDefinition的注册过程,BeanDefinition就是数据。如上面代码所示,doGetBean()方法不涉及复杂的算法,但是这个过程也不是很简单,因为我们都知道,对于IoC容器的使用,Spring提供了很多的配置参数,每一个配置参数实际上就代表了一个IoC容器的实现特征,这些特征很多都需要在依赖注入的过程或者对Bean进行生命周期管理的过程中完成。虽然我们可以简单的将IoC容器描述成一个ConcurrentHashMap,ConcurrentHashMap只是它的数据结构而不是IoC容器的全部。

Object sharedInstance = getSingleton(beanName);如注释所说,首先回去找在容器中是不是已经存在该单例。

// DefaultSingletonBeanRegistry类
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 由于scope是singleton,所以先从缓存中取单例对象的实例,如果取到直接返回,没有取到加载bean
    Object singletonObject = this.singletonObjects.get(beanName);
    // 当想要获取的bean没有被加载,并且也没有正在被创建的时候,主动去加载bean
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 锁住单例缓存区加载bean
        synchronized (this.singletonObjects) {
            // singletonObjects ,earlySingletonObjects ,singletonFactories是一个单例实例的三种存在状态
            // 再去earlySingletonObjects中去找
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 去singletonFactories中去找对象的实例
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

在DefaultSingletonBeanRegistry类中的singletonObjects属性就是存singleton bean的地方。

如果getSingleton()为 null继续往下看,会在当前的BeanFactory中获取BeanDefinition,也就是这行方法代码:final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);在这行代码拿到BeanDefinition后,首先判断是不是singleton Bean,如果是的话,开始执行创建Bean,正是return createBean(beanName, mbd, args);这行代码。如果是原型(Prototype)Bean我们就不分析了。原型bean每次执行getBean()都会创建一个实例。接下来我们看createBean()方法。

createBean()的过程

首先看一下create bean的过程

Bean实例的创建
为Bean实例设置属性(属性注入,其实就是依赖注入真正发生的地方)
调用Bean的初始化方法

前面说了getBean()是依赖注入的起点,之后会调用createBean(),下面通过createBean()代码来了解这个过程。在这个过程中,Bean对象会根据BeanDefinition定义的要求生成。

// AbstractAutowireCapableBeanFactory类
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    ...
    try {
        // 验证以及准备override的方法
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }
    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        // createBean之前调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法
        // 默认不做任何处理所以会返回null
        // 但是如果我们重写了这两个方法,那么bean的创建过程就结束了,这里就为以后的annotation自动注入提供了钩子
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }
    try {
        // 实际执行createBean的是doCreateBean()方法
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

接着往下看doCreateBean()方法。

// AbstractAutowireCapableBeanFactory类
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {
    // BeanWrapper是用来持有创建出来的Bean对象
    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    // 如果是单例,先把缓存中的同名Bean清除
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // 这里是创建Bean的地方,由createBeanInstance完成。
    // TODO 完成Bean初始化过程的第一步:创建实例
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 是否自动解决循环引用
    // 当bean条件为: 单例&&允许循环引用&&正在创建中这样的话提早暴露一个ObjectFactory
    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");
        }
        // 把ObjectFactory放进singletonFactories中
        // 这里在其他bean在创建的时候会先去singletonFactories中查找有没有beanName到ObjectFactory的映射
        // 如果有ObjectFactory就调用它的getObject方法获取实例
        // 但是在这里就可以对一个bean进行保证,代理等等AOP就可以在getEarlyBeanReference这里实现
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // TODO 完成Bean初始化过程的第二步:为Bean的实例设置属性
        // Bean依赖注入发生的地方
        // 对bean进行属性填充,如果存在依赖于其他的bean的属性,则会递归的调用初始化依赖的bean
        populateBean(beanName, mbd, instanceWrapper);
        // TODO 完成Bean初始化过程的第三步:调用Bean的初始化方法(init-method)
        // 调用初始化方法,比如init-method方法指定的方法
        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) {
        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<>(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.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        // 注册销毁方法,比如:可以在配置bean的时候指定destory-method方法
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

结合上面的代码,我们再来看一下创建Bean的三个步骤,是不是有点豁然开朗的感觉。别着急继续往下看。

Bean实例的创建,instanceWrapper = createBeanInstance(beanName, mbd, args);
为Bean实例设置属性,populateBean(beanName, mbd, instanceWrapper);
调用Bean的初始化方法,exposedObject = initializeBean(beanName, exposedObject, mbd);
createBeanInstance():Bean实例的创建
// AbstractAutowireCapableBeanFactory类
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    // 确认需要创建的Bean的实例的类可以实例化
    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());
    }

    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    // 当有工厂方法的时候使用工厂方法初始化Bean,就是配置的时候指定FactoryMethod属性,类似注解中的@Bean把方法的返回值作为Bean
    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) {
            // 如果有有参数的构造函数,构造函数自动注入
            // 这里spring会花费大量的精力去进行参数的匹配
            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);
    }

    // No special handling: simply use no-arg constructor.
    // 使用默认的构造函数对Bean进行实例化
    return instantiateBean(beanName, mbd);
}

我们可以看到在instantiateBean()方法中生成了Bean所包含的Java对象,这个对象的生成有很多种不同的方式,可以通过工厂方法生成,也可以通过容器的autowire特性生成,这些生成方式都是由BeanDefinition决定的。对于上面我们的WebController和WebService两个类是通过最后一行,使用默认的构造函数进行Bean的实例化。

接着看instantiateBean()方法。

// AbstractAutowireCapableBeanFactory类
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    // 使用默认的实例化策略对Bean进行实例化,默认的实例化策略是CglibSubclassingInstantiationStrategy,
    // 也就是常说的CGLIB来对Bean进行实例化。PS:面试官常问的字节码增强
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                    getInstantiationStrategy().instantiate(mbd, beanName, parent),
                    getAccessControlContext());
        }
        else {
            // getInstantiationStrategy()会返回CglibSubclassingInstantiationStrategy类的实例
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

这里使用CGLIB进行Bean的实例化。CGLIB是一个常用的字节码生成器的类库,其提供了一系列的API来提供生成和转换Java字节码的功能。在Spring AOP中同样也是使用的CGLIB对Java的字节码进行增强。在IoC容器中,使用SimpleInstantiationStrategy类。这个类是Spring用来生成Bean对象的默认类,它提供了两种实例化Java对象的方法,一种是通过BeanUtils,它使用的是JVM的反射功能,一种是通过CGLIB来生成。

getInstantiationStrategy()方法获取到CglibSubclassingInstantiationStrategy实例,instantiate()是CglibSubclassingInstantiationStrategy类的父类SimpleInstantiationStrategy实现的。

// SimpleInstantiationStrategy类
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
    // 如果BeanFactory重写了Bean内的方法,则使用CGLIB,否则使用BeanUtils
    if (!bd.hasMethodOverrides()) {
        // 如果bean没有需要动态替换的方法就直接反射进行创建实例
        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(
                                (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    } else {
                        constructorToUse = clazz.getDeclaredConstructor();
                    }
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                } catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        // 通过BeanUtils进行实例化,这个BeanUtils的实例化通过Constructor类实例化Bean
        // 在BeanUtils中可以看到具体的调用ctor.newInstances(args)
        return BeanUtils.instantiateClass(constructorToUse);
    } else {
        // Must generate CGLIB subclass.
        // TODO 使用CGLIB实例化对象
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

在SpringBoot中我们一般采用@Autowire的方式进行依赖注入,很少采用像SpringMVC那种在xml中使用<lookup-method>或者<replaced-method>等标签的方式对注入的属性进行override,所以在上面的代码中if(!bd.hasMethodOverrides())中的判断为true,会采用BeanUtils的实例化方式。

populateBean();属性设置(依赖注入)
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // Skip property population phase for null instance.
            return;
        }
    }
    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
    boolean continueWithPropertyPopulation = true;
    // 调用InstantiationAwareBeanPostProcessor  Bean的后置处理器,在Bean注入属性前改变BeanDefinition的信息
    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;
    }
    // 这里取得在BeanDefinition中设置的property值,这些property来自对BeanDefinition的解析
    // 用于在配置文件中通过<property>配置的属性并且显示在配置文件中配置了autowireMode属性
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    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.
        // 这里对autowire注入的处理,autowire by name
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // Add property values based on autowire by type if applicable.
        // 这里对autowire注入的处理, autowire by type
        // private List<Test> tests;
        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) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // TODO @Autowire @Resource @Value @Inject 等注解的依赖注入过程
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
    if (pvs != null) {
        // 注入配置文件中<property>配置的属性
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

上面方法中的applyPropertyValues()方法基本都是用于SpringMVC中采用xml配置Bean的方法。我们主要看的是pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);这行代码,这行代码是真正执行采用@Autowire @Value 等注解的依赖注入过程。

接着往下看

// AutowiredAnnotationBeanPostProcessor类
@Override
public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    // 遍历,获取@Autowire,@Resource,@Value,@Inject等具备注入功能的注解
    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;
}

AutowiredAnnotationBeanPostProcessor类实现了postProcessPropertyValues()方法。findAutowiringMetadata(beanName, bean.getClass(), pvs);方法会寻找在当前类中的被@Autowire,@Value等具备注入功能的注解的属性。

metadata.inject(bean, beanName, pvs);方法开始执行注入的逻辑。

// AutowiredAnnotationBeanPostProcessor类
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    // 需要注入的字段
    Field field = (Field) this.member;
    // 需要注入的属性值
    Object value;
    if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    } else {
        // @Autowired(required = false),当在该注解中设置为false的时候,如果有直接注入,没有跳过,不会报错。
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
        Assert.state(beanFactory != null, "No BeanFactory available");
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            // 通过BeanFactory 解决依赖关系
            // 比如在webController中注入了webService,这个会去BeanFactory中去获取webService,也就是getBean()的逻辑。
            // 如果存在直接返回,不存在再执行createBean()逻辑。
            // 如果在webService中依然依赖,依然会去递归。
            // 这里是一个复杂的递归逻辑。
            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) &&
                                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);
    }
}

看这行代码:value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);注意beanFactory依旧是我们熟悉的IoC容器的具体产品,也就是实现类DefaultListableBeanFactory。见到就说一遍,方便大家记住它,很重要。

在resolveDependency()方法中经过一顿操作,最终又会来到上面的getBean()方法。以上就是依赖注入的整个过程。

initializeBean():调用Bean的初始化方法

设置Bean的初始化方法有两种方法,一种是在xml或者@Bean指定init-method方法。另一种是让bean实现InitializingBean接口重写afterPropertiesSet()方法。

// AbstractAutowireCapableBeanFactory类
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的初始化方法之前,调用一系列的aware接口实现,把相关的BeanName,BeanClassLoader,以及BeanFactory注入到Bean中去。
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 这些都是钩子方法,在反复的调用,给Spring带来了极大的可拓展性
        // 初始化之前调用BeanPostProcessor
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 调用指定的init-method方法
        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()) {
        // 这些都是钩子方法,在反复的调用,给Spring带来了极大的可拓展性
        // 初始化之后调用BeanPostProcessor
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

在调用Bean的初始化方法之前,调用一系列的aware接口实现,把相关的BeanName,BeanClassLoader,以及BeanFactory注入到Bean中去。接着会执行invokeInitMethods()方法。

// AbstractAutowireCapableBeanFactory类
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    // 除了使用init-method指定的初始化方法,还可以让bean实现InitializingBean接口重写afterPropertiesSet()方法
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            // 执行afterPropertiesSet()方法进行初始化
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    // 先执行afterPropertiesSet()方法,再进行init-method
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

可见该方法中首先判断Bean是否配置了init-method方法,如果有,那么通过invokeCustomInitMethod()方法来直接调用。其中在invokeCustomInitMethod()方法中是通过JDK的反射机制得到method对象,然后调用的init-method。最终完成Bean的初始化。

 

备注:因为篇幅太长,所以里面的一些代码可能会因为版本关系导致代码不完全一样,但是处理逻辑基本是一样的。

转自:

https://www.cnblogs.com/hello-shf/category/1456313.html

 

posted @ 2020-11-29 14:38  codedot  阅读(1042)  评论(0编辑  收藏  举报