SpringBoot启动类@SpringBootApplication注解背后的秘密

在用SpringBoot的项目的时候,会发现不管干什么都离不开启动类,他是程序唯一的入口,那么他究竟为我们做了什么?本篇文章主要解析@SpringBootApplication。

一、启动类

@SpringBootApplication
public class Application {

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

}

二、@SpringBootApplication

@SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是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 {

}

点进去会发现他的注解类当中还有很多注解,就是一个自定义组合注解。

接下来来对他组合的注解一一讲解。

1、@Target(ElementType.TYPE)

@Target说明了Annotation(注解)所修饰的对象范围
取值(ElementType)有:

1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

2、@Retention(RetentionPolicy.RUNTIME)

注解按生命周期来划分可分为3类:

1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;

3、@Documented

这个注解只是用来标注生成javadoc的时候是否会被记录。

在自定义注解的时候可以使用@Documented来进行标注,如果使用@Documented标注了,在生成javadoc的时候就会把@Documented注解给显示出来。

4、@Inherited

@Inherited是一个标识,用来修饰注解,自定义注解当中会用到

首先自定义一个注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ATable {
  public String name() default "";
}

以下是在使用自定义注解的一个场景。

类继承关系中@Inherited的作用
类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解

@ATable
public class InheritedBase {
}
public class MyInheritedClass extends InheritedBase {
}

接口继承关系中@Inherited的作用
接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰

@ATable
public interface IInheritedInterface {
}
public interface IInheritedInterfaceChild extends IInheritedInterface {
}

类实现接口关系中@Inherited的作用
类实现接口时不会继承任何接口中定义的注解

@ATable
public interface IInheritedInterface {
}
public class MyInheritedClassUseInterface implements IInheritedInterface {
}

5、@SpringBootConfiguration

标注在某个类上,表示这是一个Spring Boot的配置类

点进去会发现,他其实也是一个自定义注解

@Configuration学spring的应该对他不陌生
作用:指定当前类是一个配置类,在使用spring的时候刚开始都是xml配置,也正是这个注解,开启了类配置方式。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

6、@EnableAutoConfiguration

以前我们需要配置的东西,Spring Boot会帮我们自动配置;

@EnableAutoConfiguration告诉SpringBoot开启自 动配置功能;这样自动配置才能生效;

点进去会发现@Import,说白了他就是借助@Import的支持,收集和注册特定场景相关的bean定义。

@Import作用:用于导入其他的配置类

而@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,仅此而已!

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

}

EnableAutoConfigurationImportSelector:导入哪些组件的选择器;
会给容器中导入非常多的自动配置类(xxxAutoConfiguration);

大概的流程就是:

Spring Boot在启动的时候,通过EnableAutoConfigurationImportSelector类,从类路径下的
META-INF/spring.factories中获取EnableAutoConfiguration指定的值(就是上方截图),
以全类名反射的创建方式,将这些值作为自动配置类导入到容器中,自动配置类就生效,
帮我们进行自动配置工作;

以前我们需要自己配置的东西,自动配置类都帮我们配置好了,这也就是使用springboot在使用spring,springmvc不用配置视图解析器、数据库连接池、事务 等配置的原因。直接开箱即用。

当然springboot也给我提供了修改配置的方法,那就是通过yml或者propertie文件来进行修改springboot为我们配置好的配置默认值。

7、@ComponentScan

作用:用于通过注解指定spring在创建容器时要扫描的包

我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。

@ComponentScan("com.gzl")

这也就是springboot启动类为什么放在包外的原因。

三、不使用这个注解能否启动项目

把@SpringBootApplication换成以下三个注解,照样可以正常启动。

package com.gzl.cn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

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

}

到此这篇关于SpringBoot启动类@SpringBootApplication注解背后的秘密的文章就介绍到这了,更多相关@SpringBootApplication注解背后的秘密内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解SpringBoot启动类的扫描注解的用法及冲突原则

    背景 SpringBoot 启动类上,配置扫描包路径有三种方式,最近看到一个应用上三种注解都用上了,代码如下: @SpringBootApplication(scanBasePackages ={"a","b"}) @ComponentScan(basePackages = {"a","b","c"}) @MapperScan({"XXX"}) public class XXApplic

  • springBoot项目启动类启动无法访问的解决方法

    网上也查了一些资料,我这里总结.下不来虚的,也不废话. 解决办法: 1.若是maven项目,则找到右边Maven Projects --->Plugins--->run(利用maven启动)则可以加载到webapp资源 2.上面方法治标不治本.在项目的pom文件中添加<bulid>标签标注路径即可,pom.xml后部分代码如下: 刷新maven加载,重启项目.若还是无法访问,重新导入项目 <dependencies> xxxxxxxxxxxx </dependen

  • SpringBoot为啥不用配置启动类的实现

    前言 在学习SparkJava.Vert.x等轻量级Web框架的时候,都遇到过打包问题,这两个框架打包的时候都需要添加额外的Maven配置,并指定启动类才能得到可执行的JAR包: 而springboot项目,似乎都不需要额外的配置,直接package就可以得到可执行的JAR包,这是怎么回事呢? Vert.x要怎么配? 我们先来看看,Vert.x打包做哪些配置 1)引入maven-shade-plugin插件 2)在插件中指定在package完成时触发shade操作 3)指定启动类 <plugin

  • SpringBoot启动类@SpringBootApplication注解背后的秘密

    在用SpringBoot的项目的时候,会发现不管干什么都离不开启动类,他是程序唯一的入口,那么他究竟为我们做了什么?本篇文章主要解析@SpringBootApplication. 一.启动类 @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } } 二.@SpringBoo

  • 基于SpringBoot启动类静态资源路径问题

    目录 SpringBoot启动类静态资源路径 SpringBoot核心配置类 分别是一下四个静态资源路径 静态文件存放位置设置 默认配置 自定义位置 SpringBoot启动类静态资源路径 SpringBoot核心配置类 SpringBoot核心JAR包-->spring-boot-autoconfigure-2.2.6.RELEASE.jar 其下面有-->org.springframework.boot.autoconfigure.web 其中有类-->ResourcePropert

  • springboot启动类如何剔除扫描某个包

    启动类剔除扫描某个包 排除api中不引数据库导致的报错包 @ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX,pattern = "com.integration.aop.log.service.*") }) 通过该注解配置,可以实现剔除某个包,让Spring不自动扫描该包下的内容. 适用于依赖api或者其他包时,一些不必要或不支持的对象被扫描到,引发的报错或内存占用等问题.通过

  • 详解springboot测试类注解

    目录 创建一个TextHello类 注解 主启动类 配置文件格式 区别 创建一个TextHello类 TextHello类的代码如下 @Controller @RequestMapping("/hello") public class TextHello { @GetMapping("/hello") @ResponseBody public String hello(){ return "hello,程程呀"; } } 我是在pom.xml文件

  • SpringBoot启动及自动装配原理过程详解

    一.servlet2(老spring-mvc) 配置文件: web.xml:主要配置项目启动项 application-context.xml:主要配置项目包扫描.各种bean.事务管理 springMVC.xml:主要配置controller包扫描.视图解析器.参数解析器 启动过程: 每一个spring项目启动时都需要初始化spring-context,对于非web项目可以在程序main方法中触发这个context的初始化过程. 由于web项目的启动入口在容器,所以开发者不能直接触发sprin

  • SpringBoot入口类和@SpringBootApplication讲解

    目录 入口类和@SpringBootApplication @ComponentScan相关使用 @EnableAutoConfiguration 关闭自动配置 为什么是SpringBoot SpringBoot主程序类,主入口类 主程序类,主入口类 入口类和@SpringBootApplication SpringBoot项目创建完成之后默认会生成一个*Application的入口类,通过该类的main方法即可启动SpringBoot项目. @SpringBootApplication(exc

  • 基于SpringBoot开机启动与@Order注解

    目录 SpringBoot开机启动与@Order注解 spring @Order标记 @Order标记定义了组件的加载顺序 使用spring 3.x 和spring 4.x 的例子 SpringBoot开机启动与@Order注解 package com.example.zcw.runner; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.spri

  • SpringBoot启动多数据源找不到合适的驱动类问题

    目录 启动多数据源找不到合适的驱动类 问题 这两个jar包放在一起就找不到合数的驱动加载了 启动springboot提示驱动异常 Failed to determine a suitable driver class 在pom.xml中的build标签中添加如下代码 启动多数据源找不到合适的驱动类 问题 我项目中使用了SpringBoot多数据源,但是mysql有使用阿里的Druid连接池. <!--主从配置依赖--> <dependency> <groupId>com

随机推荐