springboot启动原理及bean的初始化和自动注入

@SpringBootApplication
public class ServletInitializer extends SpringBootServletInitializer {
   public static void main(String[] args) throws Exception {
      SpringApplication app = new SpringApplication(ServletInitializer.class);//创建SpringApplication对象
      app.run(args);//运行
   }

//上面的这段代码是一个典型的springboot启动代码,接下来分析下具体的源码

public SpringApplication(Object... sources) {//实例化SpringApplication对象,入参是一个可变参数
    this.bannerMode = Mode.CONSOLE;//默认的横幅模式console
    this.logStartupInfo = true;//是否打印启动日志默认为true
    this.addCommandLineProperties = true;//添加命令行属性默认为true
    this.headless = true;//无显示器模式,默认为true
    this.registerShutdownHook = true;//默认注册一个关闭应用的钩子函数,可以实现springboot优雅关闭
    this.additionalProfiles = new HashSet();//额外的描述
    this.initialize(sources);//初始化
}

 

private void initialize(Object[] sources) {//初始化
    if (sources != null && sources.length > 0) {//如果传入的参数不为空
        this.sources.addAll(Arrays.asList(sources));//将数组转成list并添加
    }

    this.webEnvironment = this.deduceWebEnvironment();//判断当前系统环境

    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));//初始化spring.factories里的ApplicationContextInitializer对象的实例
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));//初始化spring.factories里的ApplicationListener对象的实例
    this.mainApplicationClass = this.deduceMainApplicationClass();//在方法栈里找出包含main方法的类作为启动类
}

 

private boolean deduceWebEnvironment() {//判断当前系统环境
    String[] var1 = WEB_ENVIRONMENT_CLASSES;
//private static final String[] WEB_ENVIRONMENT_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
    int var2 = var1.length;
    for(int var3 = 0; var3 < var2; ++var3) {//遍历数组
        String className = var1[var3]
        if (!ClassUtils.isPresent(className, (ClassLoader)null)) {//判断当前有没有引入web相关的jar包,没有引入则是false
            return false;
        }
    }

    return true;//返回true(我们这里是web项目)
}
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {//获取路径下jar包里的spring.factories文件
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();//获取当前线程类加载器
    Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));//加载spring.factories文件
    List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);//根据spring.factories映射的类名创建该类的实例
    AnnotationAwareOrderComparator.sort(instances);//根据order优先级排序
    return instances;//返回排序好的实例
}
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {//加载spring.factories文件
    String factoryClassName = factoryClass.getName();//获取传入的类的全类名
    try {
        Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");//获取jar包里的spring.factories文件
        ArrayList result = new ArrayList();
        while(urls.hasMoreElements()) {//遍历所有的文件
            URL url = (URL)urls.nextElement();
            Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));//将spring.factories加载成properties文件
            String factoryClassNames = properties.getProperty(factoryClassName);//根据class类名为key获取具体的spring.factories里的具体映射的类名
            result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));//放入list中
        }
        return result;//返回
    } catch (IOException var8) {//抛异常
        throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
    }
}
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {//根据spring.factories映射的类名创建该类的实例
    List<T> instances = new ArrayList(names.size());//初始化list,这里构造传入了一个指定长度,避免扩容
    Iterator var7 = names.iterator();//获取迭代器

    while(var7.hasNext()) {//遍历
        String name = (String)var7.next();//获取类名

        try {
            Class<?> instanceClass = ClassUtils.forName(name, classLoader);//通过反射来创建class对象
            Assert.isAssignable(type, instanceClass);//断言判断新创建的class是否为type类型
            Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);//获取公开的构造器
            T instance = BeanUtils.instantiateClass(constructor, args);//根据构造器实例化对象
            instances.add(instance);//将初始化完成的实例放入list中
        } catch (Throwable var12) {//抛出异常
            throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
        }
    }

    return instances;
}

 

以上是创建SpringApplication对象的过程以及需要做的处理,下面是如何运行的run方法

public ConfigurableApplicationContext run(String... args) {//运行方法
    StopWatch stopWatch = new StopWatch();//创建StopWatch对象(spring的一个计时器,用于统计和展示程序运行耗时)
    stopWatch.start();//启动计时器
    ConfigurableApplicationContext context = null;声明ConfigurableApplicationContext对象
    FailureAnalyzers analyzers = null;声明FailureAnalyzers对象(失败解析器)
    this.configureHeadlessProperty();
//System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
//设置无显示器模式,即没有检测到显示器,也允许启动,因为对于服务器来说,是不需要显示器的,因此这样设置

    SpringApplicationRunListeners listeners = this.getRunListeners(args);//获取SpringApplicationRunListener类的实例
    listeners.starting();//启动(遍历list中所有的SpringApplicationRunListeners实例并调用stating()方法)
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//解析相关的配置参数并封装成
ApplicationArguments对象
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);//环境准备(此时获取的是StandardServletEnvironment)
        Banner printedBanner = this.printBanner(environment);//获取需要打印的横幅
        context = this.createApplicationContext();//创建ApplicationContext对象
        new FailureAnalyzers(context);//实例化FailureAnalyzers对象(从spring.factories中加载FailureAnalyzer的实现类并实例化,最终每个对象都会调用setBeanFactory对象设置beanFactory为DefaultListableBeanFactory)
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);//准备处理Context(给相关的类设置Context对象,已经注册一些必要的配置bean)
        this.refreshContext(context);//刷新Spring容器(核心方法)
        this.afterRefresh(context, applicationArguments);//后置刷新
        listeners.finished(context, (Throwable)null);//监听完成
        stopWatch.stop();//停止stopWatch
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }

        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
        throw new IllegalStateException(var9);
    }
}

 

protected ConfigurableApplicationContext createApplicationContext() {创建ApplicationContext对象
    Class<?> contextClass = this.applicationContextClass;//获取当前的applicationContextClass对象,此时为空
    if (contextClass == null) {//若为空
        try {
            contextClass = Class.forName(this.webEnvironment ? "org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext" : "org.springframework.context.annotation.AnnotationConfigApplicationContext");//根据当前运行环境创建对应的ApplicationContext class对象,此时为web环境,因此是AnnotationConfigEmbeddedWebApplicationContext
        } catch (ClassNotFoundException var3) {
            throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
        }
    }

    return (ConfigurableApplicationContext)BeanUtils.instantiate(contextClass);//实例化AnnotationConfigEmbeddedWebApplicationContext对象
}
public void refresh() throws BeansException, IllegalStateException {//刷新spring容器
    synchronized(this.startupShutdownMonitor) {//线程安全
        this.prepareRefresh();//刷新前预处理(初始化容器需要的一些配置参数信息)
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();//获取BeanFactory(DefaultListableBeanFactory对象)
        this.prepareBeanFactory(beanFactory);//预处理DefaultListableBeanFactory(设置一些必要的对象属性信息)
        try {
            this.postProcessBeanFactory(beanFactory);//处理beanFactory对象
            this.invokeBeanFactoryPostProcessors(beanFactory);//处理一些自动配置类的信息并生成bean 比方说一些自动配置类,Configuration注解bean注解import注解componentScan注解等信息(这里调用栈太深了,懒得贴代码,有兴趣自己看)
            this.registerBeanPostProcessors(beanFactory);//添加BeanPostProcessors对象的实现类,并在bean实例化显示之前调用
            this.initMessageSource();//初始化国际化资源信息(有配置messageSourcebean,则获取该bean,否则创建DelegatingMessageSource对象)
            this.initApplicationEventMulticaster();//初始化应用相关的监听器
            this.onRefresh();//这里主要就是启动内置的web容器比方说Tomcat或jetty
            this.registerListeners();//发布及注册监听器
            this.finishBeanFactoryInitialization(beanFactory);//自动注入完成beanFactory的初始化创建单例的bean的实例(调用前置后置的处理方法,调用Aware接口的子类,调用afterPropertySet方法和自定义的初始化方法)
            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();
        }

    }
}
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {//处理beanFactory
    super.postProcessBeanFactory(beanFactory);//设置beanFactory
    if (this.basePackages != null && this.basePackages.length > 0) {//如果有设置包路径
        this.scanner.scan(this.basePackages);//调用扫描(默认将含有Component注解的类以及包含Component注解的注解类直接注册成spring的bean调用findCandidateComponents方法获取含有Component的类)
    }

    if (this.annotatedClasses != null && this.annotatedClasses.length > 0) {//如果有设置annotatedClasses,则直接进行bean注册
        this.reader.register(this.annotatedClasses);//注册bean
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值