当前位置: 移动技术网 > IT编程>开发语言>Java > SpringBoot原理讲解

SpringBoot原理讲解

2019年12月10日  | 移动技术网IT编程  | 我要评论

懦弱的快乐漫画,孟天娇,骑士风云修改版

一.问题的引入

首先我们来看一个最简单的例子。

我们先创建一个springboot的工程,如何创建一个springboot工程就不说了,不会请自行解决。然后写一个controller类,通过请求路径,返回helloworld在浏览器页面上显示。

        

  上面两张图就是程序的一个整体的结构和运行的结果,那么问题来了,springboot程序中没有任何配置,不像spring框架,写一大堆配置信息在xml文件中,那么程序是怎么将我们这里的controller类扫描到spring容器中的呢?

二.原理讲解。

首先第一点,我们来看一下springboot的启动类,

package com.example.demo;



import org.springframework.boot.springapplication;

import org.springframework.boot.autoconfigure.springbootapplication;



@springbootapplication

public class demoapplication {



    public static void main(string[] args) {

        //启动springboot应用

        springapplication.run(demoapplication.class, args);

    }

}

  

其中,我们看到一个注解@springbootapplication,springboot应用标注在某个类上说明这个类是springboot的主配置类,springboot就应该运行这个类的main方法来启动springboot应用;

然后我们点进去看看这个注解到底包含了什么,

@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 {      

  

其中我们需要重点关注的就是@springbootconfiguration、@enableautoconfiguration

下面我们逐个来讲解:

@springbootconfiguration这个注解顾名思义,标注在某个类上,这个类就是springboot的配置类,我们再点进去看看。

@target(elementtype.type)

@retention(retentionpolicy.runtime)

@documented

@configuration

  

 

原来这个注解是底层是spring中的注解@configuration,而@configuration注解底层就是一个@component,代表一个容器。

 

 

springboot的精髓是在@enableautoconfiguration这个注解上,根据名字,我们可以知道这是一个自动配置类,也就是能够实现一些自动配置的功能,那么具体是配置了什么东西呢?

我们再点进去看看

@target(elementtype.type)

@retention(retentionpolicy.runtime)

@documented

@inherited

@autoconfigurationpackage

@import(autoconfigurationimportselector.class)

  

我们看见了和这个注解有关联的重要的两个注解@autoconfigurationpackage,@import(autoconfigurationimportselector.class),也是分别给大家讲解一下。

1.@autoconfigurationpackage

@autoconfigurationpackage:这是一个自动配置的包,我们来看下在这个程序中是配置了哪个包,点进来

@import(autoconfigurationpackages.registrar.class)

  

 

再点到register,我们看到在大概123行的位置,有一段代码。

@override

public void registerbeandefinitions(annotationmetadata metadata, beandefinitionregistry registry) {

   register(registry, new packageimport(metadata).getpackagename());

}

  

我们看到这个方法器中一个参数metadata,代表注解的元信息,然后我们通过这个注解的元信息来获这个包名,我们在这打个断点,debug运行,可以看见一些元信息的基本内容,最主要我们要知道是导入了哪个包,我们选中new packageimport(metadata).getpackagename(),右键计算一下

发现导入的包就是我们项目的根目录,假如我们新建一个包叫com.controller,在里面写一个controller类,大家可以运行的试一下是否能成功呢。

 

2.@import(autoconfigurationimportselector.class)

     @import(autoconfigurationimportselector.class):这个注解代表的是一个自动配置的选择器,那么要导入哪些组件的选择器呢?

我们点进去,看到非常重要的一段。

protected autoconfigurationentry getautoconfigurationentry(autoconfigurationmetadata autoconfigurationmetadata,

      annotationmetadata annotationmetadata) {

   if (!isenabled(annotationmetadata)) {

      return empty_entry;

   }

   annotationattributes attributes = getattributes(annotationmetadata);

   list<string> configurations = getcandidateconfigurations(annotationmetadata, attributes);

   configurations = removeduplicates(configurations);

   set<string> exclusions = getexclusions(annotationmetadata, attributes);

   checkexcludedclasses(configurations, exclusions);

   configurations.removeall(exclusions);

   configurations = filter(configurations, autoconfigurationmetadata);

   fireautoconfigurationimportevents(configurations, exclusions);

   return new autoconfigurationentry(configurations, exclusions);

}

  

 这里我们获得到了一个configurations 的list集合,我们打个断点看看这个集合中到底给我们装了些什么东西。

我们发现这个configurations 里面装配了124个自动配置类,原来我们没有配置的一些信息,都通过springboot的自动配置类给我配置好了。

那么我还想知道这些类springboot程序给我们放到哪了呢,我们看到getcandidateconfigurations(annotationmetadata, attributes);

点进去,我们看到:

list<string> configurations = springfactoriesloader.loadfactorynames(getspringfactoriesloaderfactoryclass()

  

 

那么再点进去我们看看到底加载的工厂名称是啥,

try {

   enumeration<url> urls = (classloader != null ?

         classloader.getresources(factories_resource_location) :

         classloader.getsystemresources(factories_resource_location));

   result = new linkedmultivaluemap<>();

   while (urls.hasmoreelements()) {

      url url = urls.nextelement();

      urlresource resource = new urlresource(url);

      properties properties = propertiesloaderutils.loadproperties(resource);

      for (map.entry<?, ?> entry : properties.entryset()) {

         string factorytypename = ((string) entry.getkey()).trim();

         for (string factoryimplementationname : stringutils.commadelimitedlisttostringarray((string) entry.getvalue())) {

            result.add(factorytypename, factoryimplementationname.trim());

         }

      }

   }

  

我们看到其中类加载器给我们获取了资源,我们点进去,

点了这么多次,终于找到我们想要的答案了!!!

public static final string factories_resource_location = "meta-inf/spring.factories";

  

 

原来这些自动配置类都在类路径下的"meta-inf/spring.factories"

还有下面的autoconfigure包中的内容,我们也看看

这里面我们所有所用到的配置类全部由springboot给我们配置了,所以我们知道springboot表面上是零配置的,其实底层都给我们封装好了,也是方便我们程序员进行开发。

那么有些人肯定又有疑惑,springboot怎么知道给我们自动配置哪些类呢?

欲知后事如何,请关注一下作者,纯手打码字不易,也是希望和大家多多交流,一起学习,谢谢!

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网