• Springboot 启动简析


    入口程序

    首先,我们回到到梦开始的地方

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

    大道极简,上面的的代码非常简洁,背后蕴藏着何种玄机,我们一步一步来揭开。
    上面的两处地方,让我们既熟悉又陌生,分别是@SpringBootApplication 这个注解,和SpringApplication的run 方法。

    注解@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 {
    
    }
    
    

    通过上面的代码,我们可以看到,springbootApplication 这个注解是由多个注解组合而成的一个注解,接下来,我们分开看下上面的注解

    • @SpringbootConfigruation
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    public @interface SpringBootConfiguration {
        @AliasFor(  // 继承 configuration 这个注解
            annotation = Configuration.class
        )
        boolean proxyBeanMethods() default true;
    }
    

    这个注解的作用就是标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名。

    • @EnableAutoConfiguration
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)   
     // enable 类型的注解 主要就是用来Import 一些配置文件的注解,enable某个组件,便于我们理解
    public @interface EnableAutoConfiguration {
    
    	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
    	/**
    	 * 排除特定的自动配置类
    	 * @return the classes to exclude
    	 */
    	Class<?>[] exclude() default {};
    
    	/**
    	 * 排除特定的自动配置类名称,使它们永远不会加载
    	 * applied.
    	 * @return the class names to exclude
    	 * @since 1.3.0
    	 */
    	String[] excludeName() default {};
    
    }
    
    • @ComponentScan
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    @Documented
    @Repeatable(ComponentScans.class)
    public @interface ComponentScan {
        @AliasFor("basePackages")
        String[] value() default {};    
    
        @AliasFor("value")
        String[] basePackages() default {};   
    
        Class<?>[] basePackageClasses() default {};
    
        Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
    
        Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
    
        ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
    }
    

    定义了---

    浅析SpringApplication的run方法

    
             // 1. 以使用默认设置和用户提供的参数从指定的类运行
    	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    		return new SpringApplication(primarySources).run(args);
    	}
    
            //2.  真正的run 方法
           	public ConfigurableApplicationContext run(String... args) {
    		StopWatch stopWatch = new StopWatch();
    		stopWatch.start();
                    
    		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    		ConfigurableApplicationContext context = null;
    		configureHeadlessProperty();
    		SpringApplicationRunListeners listeners = getRunListeners(args);
    		listeners.starting(bootstrapContext, this.mainApplicationClass);
    		try {
    			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
    			configureIgnoreBeanInfo(environment);
    			Banner printedBanner = printBanner(environment);
    			context = createApplicationContext();
    			context.setApplicationStartup(this.applicationStartup);
    			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
    			refreshContext(context);
    			afterRefresh(context, applicationArguments);
    			stopWatch.stop();
    			if (this.logStartupInfo) {
    				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
    			}
    			listeners.started(context);
    			callRunners(context, applicationArguments);
    		}
    		catch (Throwable ex) {
    			handleRunFailure(context, ex, listeners);
    			throw new IllegalStateException(ex);
    		}
    
    		try {
    			listeners.running(context);
    		}
    		catch (Throwable ex) {
    			handleRunFailure(context, ex, null);
    			throw new IllegalStateException(ex);
    		}
    		return context;
    	}
    
    
  • 相关阅读:
    [Linux] day04——Linux 入门
    react 资源汇总
    画原型图工具
    Atom 插件安装
    react 编写组件 五
    webstom 配置git 后左侧菜单栏配色调整
    Webstorm 不识别es6 import React from ‘react’——webstorm不支持jsx语法怎么办
    Es6 之for of
    一个react的完整项目展示
    前后端分离 接口管理神器——Rap本地搭建
  • 原文地址:https://www.cnblogs.com/liuyupen/p/14202965.html
Copyright © 2020-2023  润新知