spring-boot 详细源码分析 启动(一)

1.1基本依懒

<!--用于版本管理-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
</parent>
<groupId>com.xie.java</groupId>
<artifactId>spring-boot-src</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

依懒继承数

1.2模块介绍

从上图可以看到spring-boot 是基于spring实现的,应用spring-boot 一般要制作starter,下面分析组成的几个模块

  1. spring-boot-starter
    该模块主要其它几个模块依赖组合在一起,实现就是一个pom文件,是没有源码
  2. spring-boot
    核心模块,完全基于spring实现
  3. spring-boot-autoconfigure
    自动配模块,基于spring-boot,预设一些常用框架的配置信息;基于依赖条件是否满足,如依赖条件满足则启用该框加配置;如mybatis,spring-aop这些框架;当然我们要自动配置这个框架首先基于spring-boot去制相应的starter
  4. spring-core
    这个不用说了

1.3简单启动代码

@EnableAutoConfiguration()//启用自动配置注解
@ComponentScan({"com.xie.java"})
public class MyBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBootApplication.class);

    }
}

1.3 加载初始化器及application监听器

public SpringApplication(ResourceLoader resourceLoader, Object... sources) {
    this.resourceLoader = resourceLoader;
    initialize(sources);
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //检测是否为web环境
    this.webEnvironment = deduceWebEnvironment();
    //从META-INFO/spring-factories里获取ApplicationContextInitializer配置的application初始化器的实现
    setInitializers((Collection) getSpringFactoriesInstances(
            ApplicationContextInitializer.class));
    //同理获取spring-factories 里配置的 application监听器
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}
//找出main方法主类
private Class<?> deduceMainApplicationClass() {
    try {
        StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            if ("main".equals(stackTraceElement.getMethodName())) {
                return Class.forName(stackTraceElement.getClassName());
            }
        }
    }
    catch (ClassNotFoundException ex) {
        // Swallow and continue
    }
    return null;
}

1.4 SpringApplication.run 启动

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    //1.获取运行监听器,
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.started();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                applicationArguments);
        Banner printedBanner = printBanner(environment);
        //2.创建applicationContext
        context = createApplicationContext();
        //3.启动前准备
        prepareContext(context, environment, listeners, applicationArguments,
                printedBanner);
        //4.刷新spring容器
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                    .logStarted(getApplicationLog(), stopWatch);
        }
        return context;
    }
    catch (Throwable ex) {
        handleRunFailure(context, listeners, ex);
        throw new IllegalStateException(ex);
    }
}

1.5创建application context

protected ConfigurableApplicationContext createApplicationContext() {
    Class<?> contextClass = this.applicationContextClass;
    if (contextClass == null) {
        try {//实际创建的是”org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext"
            contextClass = Class.forName(this.webEnvironment
                    ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Unable create a default ApplicationContext, "
                            + "please specify an ApplicationContextClass",
                    ex);
        }
    }
    return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}

1.6 context 刷新前准备

private void prepareContext(ConfigurableApplicationContext context,
                            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
                            ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);
    postProcessApplicationContext(context);
    applyInitializers(context);
    listeners.contextPrepared(context);//给监听器发送prepare事件
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }

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

    // Load the sources加载所有资源配置信息,可以是xml或类什么的
    Set<Object> sources = getSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[sources.size()]));//加载resource xml,annotation等资源
    listeners.contextLoaded(context);
}
1.7 context ioc容器构建过程,因为这里分析的是spring-boot所以接下来只会重点跟invokeBeanFactoryPostProcessors 方法
//spring ioc容器构建过程方法
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        //1获取beanfactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

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

            // Invoke factory processors registered as beans in the context.
            //2.spring-boot 自动装配置关键入口
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            //3.注册所有BeanPostProcessor ,aop、代理生成 等扩展都与BeanPostProcessor接口实现相关
            registerBeanPostProcessors(beanFactory);

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

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

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

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

            // Instantiate all remaining (non-lazy-init) singletons.
            //4.ioc 注入预生成实例
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值