Spring Boot源码解析,springboot源码

附3 springboot源码剖判,springboot源码剖判

 1 package com.microservice.framework;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 
 6 @SpringBootApplication
 7 public class MySpringAplication {
 8 
 9     public void run(String[] args) {
10         SpringApplication sa = new SpringApplication(MySpringAplication.class);
11         sa.run(args);
12     }
13 
14 }

SpringBoot运营进程:

1、构建SpringApplication对象

2、执行run()

一、构建SpringApplication对象

1     /**
2      * The application context will load beans from the specified sources 
3      */
4     public SpringApplication(Object... sources) {
5         initialize(sources);
6     }

说明:

  • 实例化该类的时候会加载bean到applicationContext中去
  • 此间的入参是MySpringApplication.class这样二个Class<com.microservice.framework.MySpringApplication>对象

    private final Set<Object> sources = new LinkedHashSet<Object>();
    private boolean webEnvironment;
    private Class<?> mainApplicationClass;

    private void initialize(Object[] sources) {
        if (sources != null && sources.length > 0) {
            this.sources.addAll(Arrays.asList(sources));
        }
        this.webEnvironment = deduceWebEnvironment();
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }

步骤:

  • 将盛传的MySpringApplication.class对象归入Set集结
  • 看清是或不是是web情状
  • 创建ApplicationInitializer列表
  • 初始化ApplicationListener列表
  • 初阶化主类mainApplicationClass

1.1、将盛传的MySpringApplication.class对象归入Set集结

1.2、判定是还是不是是web情状:

    private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
            "org.springframework.web.context.ConfigurableWebApplicationContext" };

    private boolean deduceWebEnvironment() {
        for (String className : WEB_ENVIRONMENT_CLASSES) {
            if (!ClassUtils.isPresent(className, null)) {
                return false;
            }
        }
        return true;
    }

注脚:通过在classpath中查阅是还是不是存在WEB_ENVIRONMENT_CLASSES那些数组中所包蕴的全部类(实际上正是2个类),即使存在那么当前景序正是二个Web应用程序,反之则不然。 

1.3、创建ApplicationContextInitializer列表

 1     private List<ApplicationContextInitializer<?>> initializers;
 2 
 3     public void setInitializers(
 4             Collection<? extends ApplicationContextInitializer<?>> initializers) {
 5         this.initializers = new ArrayList<ApplicationContextInitializer<?>>();
 6         this.initializers.addAll(initializers);
 7     }
 8 
 9     private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
10         return getSpringFactoriesInstances(type, new Class<?>[] {});
11     }
12 
13     private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
14             Class<?>[] parameterTypes, Object... args) {
15         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
16 
17         // Use names and ensure unique to protect against duplicates
18         Set<String> names = new LinkedHashSet<String>(
19                 SpringFactoriesLoader.loadFactoryNames(type, classLoader));
20         List<T> instances = new ArrayList<T>(names.size());
21 
22         // Create instances from the names
23         for (String name : names) {
24             try {
25                 Class<?> instanceClass = ClassUtils.forName(name, classLoader);
26                 Assert.isAssignable(type, instanceClass);
27                 Constructor<?> constructor = instanceClass.getConstructor(parameterTypes);
28                 T instance = (T) constructor.newInstance(args);
29                 instances.add(instance);
30             }
31             catch (Throwable ex) {
32                 throw new IllegalArgumentException(
33                         "Cannot instantiate " + type + " : " + name, ex);
34             }
35         }
36 
37         AnnotationAwareOrderComparator.sort(instances);
38         return instances;
39     }

步骤:

  • 调用SpringFactoriesLoader.loadFactoryNames(type,
    classLoader)来赢得具有Spring
    Factories的名字,(这里是收获了多个ApplicationContextInitializer完毕类的全类名,见上边)
  • 为每叁个Spring
    Factories依据读取到的名字创办其指标。(这里创办了4个目的)
  • 将创设好的指标列表排序并回到。

其中,SpringFactoriesLoader.loadFactoryNames(type, classLoader)如下:

 1     /**
 2      * The location to look for factories.
 3      * <p>Can be present in multiple JAR files.
 4      */
 5     public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
 6 
 7     /**
 8      * Load the fully qualified class names of factory implementations of the
 9      * given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given
10      * class loader.
11      */
12     public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
13         String factoryClassName = factoryClass.getName();
14         try {
15             Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
16                     ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
17             List<String> result = new ArrayList<String>();
18             while (urls.hasMoreElements()) {
19                 URL url = urls.nextElement();
20                 Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
21                 String factoryClassNames = properties.getProperty(factoryClassName);
22                 result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
23             }
24             return result;
25         }
26         catch (IOException ex) {
27             throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
28                     "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
29         }
30     }

META-INF/spring-factories

1 # Application Context Initializers
2 org.springframework.context.ApplicationContextInitializer=\
3 org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
4 org.springframework.boot.context.ContextIdApplicationContextInitializer,\
5 org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
6 org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer

说明:

  • 从具备jar获取具备的META-INF/spring-factories文件。(这里独有spring-boot-1.3.0.RELEASE.jar下有多个)
  • 遍历每一个spring-factories文件,并拿走其下key为factoryClass.getName()(这里是入参

    org.springframework.context.ApplicationContextInitializer)的value(这里有上述五个ApplicationContextInitializer完结类)

以上多少个类的效果与利益:

图片 1

 

至今,设置ApplicationContextInitialize就产生了。

小结:整个setInitializers实际上正是初阶化了SpringApplication的性质List<ApplicationContextInitializer<?>>
initializers为一个ArrayList列表,该列表中有多少个实例:

  • ConfigurationWarningsApplicationContextInitializer的实例
  • ContextIdApplicationContextInitializer的实例
  • DelegatingApplicationContextInitializer实例
  • ServerPortInfoApplicationContextInitializer实例

1.4、初始化ApplicationListener列表

 1     private List<ApplicationListener<?>> listeners;    
 2 
 3         /**
 4      * Sets the {@link ApplicationListener}s that will be applied to the SpringApplication
 5      * and registered with the {@link ApplicationContext}.
 6      * @param listeners the listeners to set
 7      */
 8     public void setListeners(Collection<? extends ApplicationListener<?>> listeners) {
 9         this.listeners = new ArrayList<ApplicationListener<?>>();
10         this.listeners.addAll(listeners);
11     }    

META-INF/spring-factories

 1 # Application Listeners
 2 org.springframework.context.ApplicationListener=\
 3 org.springframework.boot.builder.ParentContextCloserApplicationListener,\
 4 org.springframework.boot.context.FileEncodingApplicationListener,\
 5 org.springframework.boot.context.config.AnsiOutputApplicationListener,\
 6 org.springframework.boot.context.config.ConfigFileApplicationListener,\
 7 org.springframework.boot.context.config.DelegatingApplicationListener,\
 8 org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
 9 org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
10 org.springframework.boot.logging.LoggingApplicationListener

上述多个listener的功力如下:

图片 2

到现在停止,整个setListeners方法甘休,开始化了八个满含以上8个ApplicationListener实例的List集合。

 

1.5、最早化主类mainApplicationClass

 1     private Class<?> mainApplicationClass;
 2 
 3     private Class<?> deduceMainApplicationClass() {
 4         try {
 5             StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
 6             for (StackTraceElement stackTraceElement : stackTrace) {
 7                 if ("main".equals(stackTraceElement.getMethodName())) {
 8                     return Class.forName(stackTraceElement.getClassName());
 9                 }
10             }
11         }
12         catch (ClassNotFoundException ex) {
13             // Swallow and continue
14         }
15         return null;
16     }

表明:获取main()方法所在的主类Class对象,并赋值给SpringApplication的mainApplicationClass属性。

到现在,SpringApplication对象初步化完毕了。

计算:整个SpringApplication开头化的进程,就是开始化了

  • 一个包罗入参MySpringApplication.class的sources的Set<Object>
  • 贰个脚下条件是或不是是web景况的boolean webEnvironment
  • 八个带有4个ApplicationContextInitializer实例的List
  • 三个包蕴8个ApplicationListener实例的List
  • 二个main方法所在的主类的Class对象。

注意:

正文基本参照 达成,该文的小编曾经解析的很好了,小编那边再抄一回,只是为着加强回忆!!!

springboot源码深入解析,springboot源码剖析 1
package com.microservice.framework; 2 3 import
org.springframework.boot.SpringApplication; 4 import
org.springframework.boot….

 1     public ConfigurableApplicationContext run(String... args) {
 2         StopWatch stopWatch = new StopWatch();                            //设置计时器
 3         stopWatch.start();                                                //记录当前时间
 4         ConfigurableApplicationContext context = null;
 5         configureHeadlessProperty();                                    //设置java.awt.headless为true或false
 6         SpringApplicationRunListeners listeners = getRunListeners(args);//获取事件发布器(控制所有事件的执行时机)
 7         listeners.started();                                            //事件发布器发布ApplicationStartedEvent事件,所有监听了该事件的ApplicationListener实现类执行逻辑
 8         try {
 9             context = doRun(listeners, args);
10             stopWatch.stop();                                            //计时结束(记录总共花了多少时间)
11             if (this.logStartupInfo) {
12                 new StartupInfoLogger(this.mainApplicationClass)
13                         .logStarted(getApplicationLog(), stopWatch);
14             }
15             return context;
16         }
17         catch (Throwable ex) {
18             handleRunFailure(context, listeners, ex);
19             throw new IllegalStateException(ex);
20         }
21     }

 1     private ConfigurableApplicationContext doRun(SpringApplicationRunListeners listeners,
 2             String... args) {
 3         ConfigurableApplicationContext context;
 4         // Create and configure the environment
 5         ConfigurableEnvironment environment = getOrCreateEnvironment(); //创建Environment
 6         configureEnvironment(environment, args);                        //配置Environment(包括配置要使用的PropertySource和Profile)
 7         listeners.environmentPrepared(environment);                        //事件发布器发布ApplicationEnvironmentPreparedEvent事件,所有监听了该事件的ApplicationListener执行相应逻辑
 8         if (isWebEnvironment(environment) && !this.webEnvironment) {
 9             environment = convertToStandardEnvironment(environment);
10         }
11 
12         if (this.bannerMode != Banner.Mode.OFF) {
13             printBanner(environment);
14         }
15 
16         // Create, load, refresh and run the ApplicationContext
17         context = createApplicationContext();                            //创建ApplicationContext容器
18         context.setEnvironment(environment);                            //设置Environment到容器
19         postProcessApplicationContext(context);                            
20         applyInitializers(context);                                        //执行所有的ApplicationContextInitializer的initial方法,对创建出来的ApplicationContext容器进行初始化
21         listeners.contextPrepared(context);                                
22         if (this.logStartupInfo) {
23             logStartupInfo(context.getParent() == null);
24             logStartupProfileInfo(context);
25         }
26 
27         // Add boot specific singleton beans
28         ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
29         context.getBeanFactory().registerSingleton("springApplicationArguments",
30                 applicationArguments);
31 
32         // Load the sources
33         Set<Object> sources = getSources();
34         Assert.notEmpty(sources, "Sources must not be empty");
35         load(context, sources.toArray(new Object[sources.size()]));        //将之前通过@EnableAutoConfiguration的所有配置以及其他形式的IOC容器加载到已经准备完毕的ApplicationContext
36         listeners.contextLoaded(context);                                //事件发布器将所有的ApplicationListener注册给当前的ApplicationContext,之后发布ApplicationPreparedEvent事件
37 
38         // Refresh the context
39         refresh(context);                                                //刷新ApplicationContext
40         if (this.registerShutdownHook) {
41             try {
42                 context.registerShutdownHook();
43             }
44             catch (AccessControlException ex) {
45                 // Not allowed in some environments.
46             }
47         }
48         afterRefresh(context, applicationArguments);
49         listeners.finished(context, null);
50         return context;
51     }

Spring Boot源码深入深入分析,springboot源码

spring boot 源码解析–分为3个部分 

 

1.SpringApplication实例化及run方法深入分析 

2.Spring boot 自动装配 

3.Spring boot actuator 解析

 

里面提到了类加载机制,spring cache,spring mvc,spring
core等内容,全方面的为你回复:

 

1. 选择过spring boot,spring cloud
的人都会在application.properties中安插如spring.datasource.url
的安插,不过其是怎么着生效的,超多个人就不精晓了

 

2. 施用spring-boot-starter-actuator的都会配备如下内容endpoints.shutdown.enabled=true
来落实文雅关闭,但原因怎么,很五人就不晓得了

 

3. 步入spring-boot-starter-web后,不需任何操作,1个web程序就铺排好了,未有了一群配置,其幕后的密码,很三人都不领悟

….

 

课程纲要之类:

  1. Spring Boot介绍,源码阅读情状搭建,插件安装 

  2. SpringApplication初始化 

  3. SpringApplication run方法深入分析(1)–前3步 

  4. SpringApplication run方法剖析(2)—第4步 

  5. SpringApplication run方法分析(3)—第5步 

  6. SpringApplication run方法剖判(3)—第6步 

  7. SpringApplication run方法分析(3)—第7步 

  8. SpringApplication run方法深入分析(3)—第8步 

  9. SpringApplication run方法深入分析(3)—第9步 

  10. SpringApplication run方法解析(3)—第10步 

  11. ConfigurationClassPostProcessor类加载深入分析 

  12. servlet容器的确立 

  13. @ConfigurationProperties是如何生效的 

  14. ImportSelector及暗中认可错误页面

  15. spring mvc零配置 

  16. spring boot外置tomcat陈设揭秘 

  17. mvc自动化配置揭秘 

  18. WebMvcAutoConfiguration自动化配置揭秘 

  19. @Conditional注解详整 

  20. spring boot aop自动化配置 

  21. spring boot transaction自动化配置 

  22. spring boot jdbc自动化配置 

  23. actuator使用及EndPoint解析 

  24. HealthEndpoint解析 

  25. DataSourcePoolMetadata与DataSourcePoolMetadataProvider 

  26. Liquibase使用及LiquibaseEndpoint解析 

  27. JavaLoggingSystem及LoggingSystem生命周期详明 

  28. Log4J2LoggingSystem 

  29. LogbackLoggingSystem 

  30. LoggersEndpoint 

  31. AuthenticationAuditListener,AuthorizationAuditListener 

….

课程内容会四处的增加,在深入分析源码的道路上,未有尽头.该学科或多或少都会对您有所扶持.

学科地址:

Boot源码解析,springboot源码 spring boot
源码深入分析–分为3个部分 1.SpringApplication实例化及run方法深入深入分析 2.Spring
boot 自动装配 3.Spring boot actuat…

 步骤总括:

  • 安装沙漏,记录当前时间
    • 此类是二个非线程的安全的,假使自个儿行使要思索二十四线程的意况.
  • 设置java.awt.headless为true或false
    • java.awt.headless是J2SE的生龙活虎种情势用于在贫乏显示屏、键盘恐怕鼠标时的种类布署,非常多监督工具如jconsole
      须求将该值设置为true
  • 获得事件公布器(用于调整所有的事件的实行时机)
  • 事件发表器发表ApplicationStarted伊夫nt事件,全数监听了该事件的ApplicationListener完成类实践逻辑
  • 创设并配置Environment(包含布署要运用的PropertySource和Profile)

    • PropertySource根本是读取SpringApplication.setDefaultProperties钦赐的默许属性 +
      一声令下行属性

      • 日常说来,唯有命令行属性,并且该属性会addFirst,表明先行级是最高的!!!
    • Profile重借使读取application-{level}.properties中的内容
      • 供给安顿:”spring.active.profiles”
    • 关于布局文件的生机勃勃两种主题素材 见附 5
      springboot之布置文件
  • 事件公布器发布ApplicationEnvironmentPreparedEvent事件,全体监听了该事件的ApplicationListener试行相应逻辑
  • 创建ApplicationContext容器
  • 设置Environment到容器
  • 试行全数的ApplicationContextInitializer的initial方法,对创造出来的ApplicationContext容器进行开端化
  • 将事先经过@EnableAutoConfiguration的有着配置以至其余情势的IOC容器加载到已经盘算截至的ApplicationContext
    • 装载beanDefinition到ApplicationContext(之后在动用Bean的时候,直接由beanDefinition伊始化为bean)
  • 事件公布器将具备的ApplicationListener注册给当下的ApplicationContext,之后发表ApplicationPrepared伊芙nt事件
  • 刷新ApplicationContext
    • 此处假诺有ContextRefreshedEvent的监听器,那么那时就能触发其onApplication方法
  • 完工计时,记录整个运行时间

如上浅灰褐部分正是着力步骤!

 

参考:

《springboot揭秘-急忙营造微服务种类》

相关文章