Spring Boot原理分析(一):项目启动流程、自动装配

news/2024/11/29 12:48:07/

文章目录

  • 一、项目启动流程
  • 二、SpringBootApplication.java源码解析
    • 1.准备工作
    • 2.源码
    • 3.自定义注解
    • 4.组合注解
    • 5.注解@ComponentScan
      • 过滤器
    • 6.注解@SpringBootConfiguration
      • @Configuration
    • 7.注解@EnableAutoConfiguration
      • (1)Spring手动装配
        • 使用XML配置文件
        • 使用Java注解
        • 使用Java类
      • (2)Spring Boot自动装配
        • @AutoConfigurationPackage
        • @Import(AutoConfigurationImportSelector.class)

本文章是Spring Boot原理分析系列博客的第一篇,将会介绍一些准备工作和Spring Boot的项目启动的原理和源码。

一、项目启动流程

  1. 加载Spring Boot的启动类: Spring Boot应用程序的入口点是一个带有@SpringBootApplication注解的Java类。该注解会触发Spring Boot的自动配置和组件扫描。

  2. 创建Spring应用程序上下文: 在启动类中,使用SpringApplication.run()方法创建一个Spring应用程序上下文。该方法会加载所有的配置、组件和依赖,并创建一个可用于管理应用程序的上下文对象。

  3. 执行自动装配: Spring Boot会根据类路径上的依赖和配置,自动配置应用程序的各个组件。它会根据约定和默认值,自动配置数据库连接、Web服务器、日志记录等功能。

  4. 启动内嵌的Web服务器: 如果应用程序是一个Web应用程序,Spring Boot会自动启动一个内嵌的Web服务器(如Tomcat、Jetty等),并将应用程序部署到该服务器上。

  5. 运行应用程序: 一旦所有的配置和组件都加载完毕,Spring Boot会调用应用程序的主要方法,开始执行应用程序的业务逻辑。

二、SpringBootApplication.java源码解析

1.准备工作

  • 环境:
jdk 1.8 + Maven 3.3.9或以上版本 + IDEA
SpringBoot 2.7.13
  • 启动类:
    创建项目后会自动创建一个启动类,运行main方法就可以启动项目,代码如下:
package tracy.springbootcode;@SpringBootApplication
public class SpringBootCodeApplication {public static void main(String[] args) {SpringApplication.run(SpringBootCodeApplication.class, args);}}

可以说,@SpringBootApplication是其中最关键的东西。

2.源码

@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 {@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")String[] scanBasePackages() default {};@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")Class<?>[] scanBasePackageClasses() default {};@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}

3.自定义注解

关于自定义注解的相关知识可以先看我这篇博客了解一下。

以下四个元注解用于定义@SpringBootApplication这个注解:

@Target(ElementType.TYPE)//注解的作用目标是类、接口(包括注解类型)或枚举声明。
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited//此注解可被继承

4.组合注解

@SpringBootApplication是一个组合注解,它等价于同时标注 @Configuration + @EnableAutoConfiguration + @ComponentScan 。

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

在这里插入图片描述

5.注解@ComponentScan

可以指定包扫描的根路径,让 SpringFramework 来扫描指定包及子包下的组件;也可以不指定路径,默认扫描当前配置类所在包及子包里的所有组件,所以启动类才会放到所有类所在包的最外层。

@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

过滤器

这段代码是使用Spring框架中的注解来指定Spring Boot自动配置时需要排除的类。

具体来说,这里使用了两个@Filter注解,分别指定了需要排除的类的类型以及具体的类名:

  • 第一个@Filter注解的type属性值为FilterType.CUSTOM,表示需要使用自定义的过滤器来进行过滤;
    classes属性指定了具体的自定义过滤器类,这里是TypeExcludeFilter.class。 它会从 BeanFactory (可以暂时理解成IOC容器)中获取所有类型为 TypeExcludeFilter 的组件,去执行自定义的过滤方法。由此可见,TypeExcludeFilter 的作用是做扩展的组件过滤。

  • 第二个@Filter注解同样是type属性值为FilterType.CUSTOM,表示需要使用自定义过滤器;
    classes属性指定了另一个自定义过滤器类,这里是AutoConfigurationExcludeFilter.class。会将不需要自动配置的类屏蔽掉。

这两个自定义过滤器的作用是根据一定的规则来排除不需要自动配置的类。例如,TypeExcludeFilter可以排除特定类型的类,AutoConfigurationExcludeFilter可以排除不需要自动配置的类。这样就可以在Spring Boot自动配置过程中,针对某些类进行自定义的过滤和排除,从而更加灵活地控制自动配置的行为。

6.注解@SpringBootConfiguration

  • @SpringBootConfiguration的定义:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}

@SpringBootConfiguration被 @Configuration 标注,说明它实际上是标注配置类的,而且是标注主启动类的。

也就是说,在启动类上使用这个注解表明该类是一个配置类,也是当前项目的主启动类。

@Configuration

被 @Configuration 标注的类,会被 Spring 的IOC容器认定为配置类。一个被 @Configuration 标注的类,相当于一个 applicationContext.xml 的配置文件。

7.注解@EnableAutoConfiguration

这一个注解是spring boot自动装配的核心注解。

(1)Spring手动装配

Spring Framework提供了多种手动装配的方式,其中比较常见的有以下几种:

使用XML配置文件

在XML配置文件中使用<bean>元素配置需要装配的Bean对象,然后使用ClassPathXmlApplicationContext或者XmlWebApplicationContext启动Spring容器。Spring容器会自动解析XML配置文件,并将其中配置的Bean对象注册为Spring容器中的Bean对象。

示例代码如下:

<beans><bean id="myService" class="com.example.service.MyServiceImpl"/><bean id="myController" class="com.example.controller.MyController"><property name="myService" ref="myService"/></bean>
</beans>

使用Java注解

在Java类中使用@Configuration注解标记一个配置类,然后在该类中使用@Bean注解标记需要装配的Bean对象。然后使用AnnotationConfigApplicationContext启动Spring容器。Spring容器会自动扫描@Configuration注解的类,并将其中使用@Bean注解标记的方法的返回值注册为Spring容器中的Bean对象。

示例代码如下:

@Configuration
public class AppConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}@Beanpublic MyController myController() {MyController controller = new MyController();controller.setMyService(myService());return controller;}
}

使用Java类

直接在Java类中创建需要装配的Bean对象,并将其注册到Spring容器中。然后使用AnnotationConfigApplicationContext启动Spring容器。Spring容器会自动扫描Java类中注册的Bean对象,并将其注册为Spring容器中的Bean对象。

示例代码如下:

public class MyConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}@Beanpublic MyController myController() {MyController controller = new MyController();controller.setMyService(myService());return controller;}
}public class MyApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);MyController controller = context.getBean(MyController.class);// ...}
}

需要注意的是,Spring Framework的手动装配方式适用于需要对Bean进行复杂的配置或者需要根据特定条件进行Bean的选择和装配的场景。对于简单的Bean对象,使用自动装配方式更加方便快捷。

(2)Spring Boot自动装配

SpringBoot的自动配置完全由 @EnableAutoConfiguration 开启,这一注解是上一篇博客中所介绍的@SpringBootApplication注解中的组成之一。

在这里插入图片描述

从@EnableAutoConfiguration的定义可以看出,@AutoConfigurationPackage注解是它的组成之一。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {/*** Environment property that can be used to override when auto-configuration is* enabled.*/String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";/*** Exclude specific auto-configuration classes such that they will never be applied.* @return the classes to exclude*/Class<?>[] exclude() default {};/*** Exclude specific auto-configuration class names such that they will never be* applied.* @return the class names to exclude* @since 1.3.0*/String[] excludeName() default {};}

@AutoConfigurationPackage

@AutoConfigurationPackage注解的作用是将当前类所在的包及其子包中的所有类都注册到Spring Boot的自动配置中。这样,Spring Boot就可以扫描到这些类,并根据它们的特性和需求进行自动配置。

@Import(AutoConfigurationImportSelector.class)

@Import(AutoConfigurationImportSelector.class)注解的作用是让Spring Boot自动扫描classpath下的META-INF/spring.factories文件,从中获取所有的自动配置类,并将这些自动配置类导入到Spring Boot应用程序中。

spring.factories是一个标准的Java properties文件,它可以在classpath下的任何SpringFramework的jar包中找到。在这个文件中,可以通过键值对的方式指定自动配置类的全限定类名,例如:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

这个键值对指定了两个自动配置类:DataSourceAutoConfiguration和HibernateJpaAutoConfiguration。在Spring Boot启动应用程序时,Spring Boot会自动扫描到这些自动配置类,并根据它们的特性和需求进行自动配置。


http://www.ppmy.cn/news/830972.html

相关文章

树莓派无法打开摄像头模块,无法识别摄像头

折腾了一下午&#xff0c;一直以为是自己的问题&#xff0c;网上找了很多答案都没效果 换回旧系统旧可以了&#xff0c;经测试2021年1月份的系统可用 最新的10月份系统不可用

MacOS使用openCV打开摄像头

macOS 10.14 Mojave之后&#xff0c;使用opencv调用摄像头会产生权限错误&#xff0c;报错“This app has crashed because it attempted to access privacy-sensitive data without a usage description.” 原因是macOS 10.14加入了对所有程序的隐私权限管理&#xff…

Mac无法打开QQ摄像头怎么办?

首先确保已经打开电脑的声音&#xff0c;不能将电脑设置在静音状态。标志表示没有静音。反复按下F9就可以看到两个标志的切换然后关闭电脑&#xff0c;注意&#xff0c;不是重启。然后手动启动电脑&#xff0c;当听到咚一声时&#xff0c;马上同时按下四个键&#xff1a;comman…

【MAC】外接摄像头

import Cocoa import AVKit import VideoToolbox//全局 private var session: AVCaptureSession? private var videoInput: AVCaptureDeviceInput? private var videoOutput: AVCaptureVideoDataOutput?// session self.session AVCaptureSession() // 发现设备 let discov…

树莓派4B非官方摄像头+MJPG-stream显示安装全过程/踩雷记录]

树莓派4B非官方摄像头MJPG-stream显示安装全过程/踩雷记录] 前言 最近尝试树莓派非官方摄像头采集数据&#xff0c;遇到了了一些问题&#xff0c;在这里做记录。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、环境配置 1.摄像头检查 sudo raspi…

5、树莓派连接官方CSI摄像头的使用

本篇博文大部分转https://blog.csdn.net/u013162035/article/details/78580486 其中有部分细节根据自己的实际操作进行了修改 5.1树莓派基本操作 目前提供了三个应用程序&#xff0c;分别为&#xff1a;raspistill、raspivid、raspistillyuv。其中 raspistill 和 raspistillyuv…

虚拟机打开摄像头

第一步打开VMware可移动设备看看有没有摄像头选项&#xff0c;有直接连接 没有&#xff0c;打开设置看看USB控制器&#xff0c;看看兼容性 再看一下Windows下这个VMware USB arbitration 管理 USB服务打开了没有 还有这个 VMware Authorization 服务 让它打开。

解决新版树莓派无法开启CSI接口摄像头问题

博主近日想拿树莓派做个监控系统&#xff0c;于是入手了树莓派3B以及官方的Camera V2。刷了最新版的raspbian系统&#xff0c;发现怎么都无法使用。 网传的如下的图&#xff0c;然而我刷的最新的系统里根本没有这个选项。 解决方法如下&#xff1a; 首先判断一下摄像头是不是不…