欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot Application注解原理及代码详解

程序员文章站 2023-11-07 19:53:22
1、springboot 启动main()@springbootapplicationpublic class tomcatdebugapplication { public static void...

1、springboot 启动main()

@springbootapplication
public class tomcatdebugapplication {

  public static void main(string[] args) {
    springapplication.run(tomcatdebugapplication.class, args);
  }

}

1.1 @springbootapplication 注解,其实主要是@componentscan,@enableautoconfiguration,@springbootconfiguration三个注解

SpringBoot Application注解原理及代码详解

@componentscan 注解:

spring里有四大注解:@service,@repository,@component,@controller用来定义一个bean.@componentscan注解就是用来自动扫描被这些注解标识的类,最终生成ioc容器里的bean.

可以通过设置@componentscan basepackages,includefilters,excludefilters属性来动态确定自动扫描范围,类型已经不扫描的类型.

 默认情况下:它扫描所有类型,并且扫描范围是@componentscan注解所在配置类包及子包的类

@springbootconfiguration 注解:

@springbootconfiguration继承自@configuration,二者功能也一致,标注当前类是配置类,
并会将当前类内声明的一个或多个以@bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名。

demo 说明:

(1) 注入spring ioc bean

@springbootconfiguration
public class config {
  @bean
  public map createmap(){
    map map = new hashmap();
    map.put("username","gxz");
    map.put("age",27);
    return map;
  }
}

(2)调用:

public static void main( string[] args )
  {
    //方式1 获取context
    configurableapplicationcontext context = springapplication.run(app.class, args);
    context.getbean(runnable.class).run();
    context.getbean("createmap");  //注意这里直接获取到这个方法bean
    int age = (int) map.get("age");
    system.out.println("age=="+age);
//方式2. 使用@autowired注解,应用bean 
// @autowired// map createmap
}

@enableautoconfiguration 注解

@enableautoconfiguration作用:从classpath中搜索所有的meta-inf/spring.factories配置文件,然后将其中key为org.springframework.boot.autoconfigure.enableautoconfiguration的value加载到spring容器中。

SpringBoot Application注解原理及代码详解

上图分析源码可知: @enableautoconfiguration = @import + @autoconfigurationpackage

@autoconfigurationpackage:主要作用是自动配置包

@import: spring底层注解@import,给容器中导入一个组件;导入的组件由autoconfigurationpackages.registrar.class将主配置类(@springbootapplication标注的类)的所在包以及下面所有子包里面的所有组件扫描到spring容器。

autoconfigurationimportselector的作用是导入哪些组件的选择器。将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中;也会给容器导入非常多的自动配置类(xxxautoconfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件。

  有了自动配置类,免去了我们手动编写配置注入功能组件等的工作

具体工作流程图:

SpringBoot Application注解原理及代码详解

@enableautoconfiguration加载过程

 自动配置主要由autoconfigurationimportselector实现的,我们主要从这个类开始讲起。autoconfigurationimportselector是@enableautoconfiguration“@import”的deferredimportselector实现类,由于deferredimportselector作为importselector的子接口,所以组件自动配置逻辑均在selectimports(annotationmetadata)方法中实现

源码分析:  

autoconfigurationimportselector.java

根据以上代码分析自动配置加载过程主要分为以下几个步骤:

1.判断是否开启自动配置

2.从meta-inf/spring-autoconfigure-metadata.properties文件中载入属性配置

3.获取所有的配置列表

public string[] selectimports(annotationmetadata annotationmetadata) {
    //1.是否开启自动配置,默认开启
  if (!this.isenabled(annotationmetadata)) {
    return no_imports;
  } else {
    try {
        //2.从meta-inf/spring-autoconfigure-metadata.properties文件中载入属性配置(有一些有默认值),获取注解信息

      autoconfigurationmetadata autoconfigurationmetadata = autoconfigurationmetadataloader.loadmetadata(this.beanclassloader);
       
       //3.获取所有的配置列表
      annotationattributes attributes = this.getattributes(annotationmetadata);
      list<string> configurations = this.getcandidateconfigurations(annotationmetadata, attributes);
      configurations = this.removeduplicates(configurations);
      configurations = this.sort(configurations, autoconfigurationmetadata);
      set<string> exclusions = this.getexclusions(annotationmetadata, attributes);
      this.checkexcludedclasses(configurations, exclusions);
      configurations.removeall(exclusions);
      configurations = this.filter(configurations, autoconfigurationmetadata);
      this.fireautoconfigurationimportevents(configurations, exclusions);
      return (string[])configurations.toarray(new string[configurations.size()]);
    } catch (ioexception var6) {
      throw new illegalstateexception(var6);
    }
  }
}

1.是否开启自动配置,默认开启

 protected boolean isenabled(annotationmetadata metadata) {
    return true;
  }

2.从meta-inf/spring-autoconfigure-metadata.properties文件中载入属性配置

protected static final string path = "meta-inf/spring-autoconfigure-metadata.properties";

  private autoconfigurationmetadataloader() {
  }

  public static autoconfigurationmetadata loadmetadata(classloader classloader) {
    return loadmetadata(classloader, "meta-inf/spring-autoconfigure-metadata.properties");
  }
  static autoconfigurationmetadata loadmetadata(classloader classloader, string path) {
    try {
      enumeration<url> urls = classloader != null ? classloader.getresources(path) : classloader.getsystemresources(path);
      properties properties = new properties();
      while(urls.hasmoreelements()) {
        properties.putall(propertiesloaderutils.loadproperties(new urlresource((url)urls.nextelement())));
      }
      return loadmetadata(properties);
    } catch (ioexception var4) {
      throw new illegalargumentexception("unable to load @conditionalonclass location [" + path + "]", var4);
    }
  }

3、获取所有的配置列表

protected annotationattributes getattributes(annotationmetadata metadata) {
    string name = this.getannotationclass().getname();
    annotationattributes attributes = annotationattributes.frommap(metadata.getannotationattributes(name, true));
    assert.notnull(attributes, "no auto-configuration attributes found. is " + metadata.getclassname() + " annotated with " + classutils.getshortname(name) + "?");
    return attributes;
  }

总结:

springboot底层实现自动配置的步骤:

1.springboot应用启动

2.@springbootapplication起作用

3.@enableautoconfiguration

4.@autoconfigurationpackage:这个组合注解主要是@import(autoconfigurationpackages.registrar.class),它通过将registrar类导入到容器中,而registrar类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到springboot创建管理的容器中

5.@import(autoconfigurationimportselector.class):它通过将autoconfigurationimportselector类导入到容器中,autoconfigurationimportselector类作用是通过selectimports方法实现将配置类信息交给springfactory加载器进行一系列的容器创建过程,具体实现可查看上面的源码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。