SpringBoot 源碼解析 (一)----- SpringBoot核心原理入門

Spring Boot 概述

Build Anything with Spring Boot:Spring Boot is the starting point for building all Spring-based applications. Spring Boot is designed to get you up and running as quickly as possible, with minimal upfront configuration of Spring.html

上面是引自官網的一段話,大概是說: Spring Boot 是全部基於 Spring 開發的項目的起點。Spring Boot 的設計是爲了讓你儘量快的跑起來 Spring 應用程序而且儘量減小你的配置文件。java

什麼是 Spring Boot

  • 它使用 「習慣優於配置」 (項目中存在大量的配置,此外還內置一個習慣性的配置,讓你無須手動配置)的理念讓你的項目快速運行起來。
  • 它並非什麼新的框架,而是默認配置了不少框架的使用方式,就像 Maven 整合了全部的 jar 包同樣,Spring Boot 整合了全部框架

使用 Spring Boot 有什麼好處

回顧咱們以前的 SSM 項目,搭建過程仍是比較繁瑣的,須要:web

  • 1)配置 web.xml,加載 spring 和 spring mvc
  • 2)配置數據庫鏈接、配置日誌文件
  • 3)配置家在配置文件的讀取,開啓註解
  • 4)配置mapper文件
  • .....

而使用 Spring Boot 來開發項目則只須要很是少的幾個配置就能夠搭建起來一個 Web 項目,而且利用 IDEA 能夠自動生成生成spring

  • 劃重點:簡單、快速、方便地搭建項目;對主流開發框架的無配置集成;極大提升了開發、部署效率。

Spring Boot HelloWorld

導入依賴spring boot相關的依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.chenhao</groupId>
    <artifactId>springboot</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot</name>
    <description>Demo project for Spring Boot</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

編寫主程序

/** * @SpringBootApplication來標註一個主程序類,說明這是一個SpringBoot應用 */ @SpringBootApplication public class HelloWorldMainApplication { public static void main(String[] args) { //Spring應用啓動
        SpringApplication.run(HelloWorldMainApplication.class, args); } }

編寫Controller、Service

@RestController public class HelloController { @RequestMapping("/hello") public String hello(){ return "Hello world"; } }

運行主程序測試

使用maven打包命令將其打包成jar包後,直接使用命令:數據庫

java -jar xxx.jar

Hello World探究

POM文件

父項目

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath/>
</parent>

其父項目是apache

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
</parent>

該父項目是真正管理Spring Boot應用裏面的全部依賴的版本:Spring Boot的版本仲裁中心,因此之後導入的依賴默認是不須要版本號。以下tomcat

還有不少版本號沒有截圖出來springboot

啓動器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring-boot-starter : spring boot場景啓動器;幫助導入web模塊正常運行所依賴的組件;mvc

​ Spring Boot將全部的功能場景抽取出來,作成一個個的starter(啓動器),只須要在項目中引入這些starter,那麼相關的場景的全部依賴都會導入進項目中。要用什麼功能就導入什麼場景的啓動器。app

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>

添加了 spring-boot-starter-web 依賴,會自動添加 Tomcat 和 Spring MVC 的依賴

spring-boot-starter-web中又引入了spring-boot-starter-tomcat

主程序類(主入口類)

@SpringBootApplication public class HelloWorldMainApplication { public static void main(String[] args) { //Spring應用啓動
     SpringApplication.run(HelloWorldMainApplication.class, args); } }

@SpringBootApplication

  • Spring Boot應用標註在某個類上,說明這個類是SpringBoot的主配置類,SpringBoot就應該運行這個類的main方法來啓動SpringBoot應用。

註解定義以下:

@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {}

@SpringBootConfiguration

  • Spring Boot的配置類
  • 標註在某個類上,表示這是一個Spring Boot的配置類

註解定義以下:

@Configuration public @interface SpringBootConfiguration {}

其實就是一個Configuration配置類,意思是HelloWorldMainApplication最終會被註冊到Spring容器中

@EnableAutoConfiguration

  • 開啓自動配置功能
  • 之前使用Spring須要配置的信息,Spring Boot幫助自動配置;
  • @EnableAutoConfiguration通知SpringBoot開啓自動配置功能,這樣自動配置才能生效。

註解定義以下:

@AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {}

@AutoConfigurationPackage

  • 自動配置包註解
@Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage {}
@Import(AutoConfigurationPackages.Registrar.class):默認將主配置類( @SpringBootApplication)所在的包及其子包裏面的全部組件掃描到Spring容器中。以下
@Order(Ordered.HIGHEST_PRECEDENCE) static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //默認將會掃描@SpringBootApplication標註的主配置類所在的包及其子包下全部組件 register(registry, new PackageImport(metadata).getPackageName()); } @Override public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.<Object>singleton(new PackageImport(metadata)); } }

@Import(EnableAutoConfigurationImportSelector.class)

EnableAutoConfigurationImportSelector: 導入哪些組件的選擇器,將全部須要導入的組件以全類名的方式返回,這些組件就會被添加到容器中。

 1 //EnableAutoConfigurationImportSelector的父類:AutoConfigurationImportSelector
 2 @Override  3 public String[] selectImports(AnnotationMetadata annotationMetadata) {  4     if (!isEnabled(annotationMetadata)) {  5         return NO_IMPORTS;  6  }  7     try {  8         AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader  9             .loadMetadata(this.beanClassLoader); 10         AnnotationAttributes attributes = getAttributes(annotationMetadata); 11         List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); 12         configurations = removeDuplicates(configurations); 13         configurations = sort(configurations, autoConfigurationMetadata); 14         Set<String> exclusions = getExclusions(annotationMetadata, attributes); 15  checkExcludedClasses(configurations, exclusions); 16  configurations.removeAll(exclusions); 17         configurations = filter(configurations, autoConfigurationMetadata); 18  fireAutoConfigurationImportEvents(configurations, exclusions); 19         return configurations.toArray(new String[configurations.size()]); 20  } 21     catch (IOException ex) { 22         throw new IllegalStateException(ex); 23  } 24 }

咱們主要看第11行List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);會給容器中注入衆多的自動配置類(xxxAutoConfiguration),就是給容器中導入這個場景須要的全部組件,並配置好這些組件。咱們跟進去看看

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); //...
    return configurations; } protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; } public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { //從類路徑的META-INF/spring.factories中加載全部默認的自動配置類
        Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); List<String> result = new ArrayList<String>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); //獲取EnableAutoConfiguration指定的全部值,也就是EnableAutoConfiguration.class的值 String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } }
SpringBoot啓動的時候從類路徑下的 META-INF/spring.factories中獲取EnableAutoConfiguration指定的值,並將這些值做爲自動配置類導入到容器中,自動配置類就會生效,最後完成自動配置工做。EnableAutoConfiguration默認在spring-boot-autoconfigure這個包中,以下圖

最終有96個自動配置類被加載並註冊進Spring容器中

J2EE的總體整合解決方案和自動配置都在spring-boot-autoconfigure-xxx.jar中。在這些自動配置類中會經過@ConditionalOnClass等條件註解判斷是否導入了某些依賴包,從而經過@Bean註冊相應的對象進行自動配置。後面咱們會有單獨文章講自動配置的內容

 

 

 

 

 

 

原文出處:https://www.cnblogs.com/java-chen-hao/p/11829056.html

相關文章
相關標籤/搜索