• 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

  • 相关阅读:
    复杂系统架构设计<1>
    DevExpress Applications<3>
    DevExpress Skins<2>
    DevExpress MVVM<1>
    Unity容器<1>
    spring cloud微服务快速教程之(九) Spring Cloud Alibaba--sentinel-限流、熔断降级
    spring cloud微服务快速教程之(八) Spring Cloud Alibaba--nacos(二)、配置中心
    spring cloud微服务快速教程之(七) Spring Cloud Alibaba--nacos(一)、服务注册发现
    小白的springboot之路(十五)、mybatis的PageHelper分页插件使用
    spring cloud微服务快速教程之(六) 应用监控 spring boot admin
  • 原文地址:https://www.cnblogs.com/myitnews/p/14056251.html
Copyright © 2020-2023  润新知