SpringBoot原理

SpringBoot原理

配置优先级

SpringBoot中支持三种格式的配置文件

  1. application.properties(优先级最高)
  2. application.yml(推荐配置)
  3. application.yaml(优先级最低)

SpringBoot除了支持配置文件属性配置,还支持java系统属性和命令行参数的方式进行配置

  1. SpringBoot支持通过java系统属性的方式进行配置,通过-D进行配置,例如:-Dserver.port=8080
  2. 运行jar包时配置 java -jar xxx.jar --server.port=8080

Bean管理

IOC容器中获取bean对象

默认情况下,Spring项目在启动时,会自动创建IOC容器,并将Bean对象放入容器中。可以通过如下方式获取bean对象

  1. 根据name获取bean对象 Objet getBean(String name)
  2. 根据类型获取bean对象 Object getBean(Class<?> requiredType)
  3. 根据name获取bean(带类型转换):<T> T getBean(String name, Class<T> requiredType)
public class Test {
    //获取被ioc容器管理的bean对象
    //注入ioc容器对象
    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void test01() {
        //默认获取出来是一个Object 类型,需要进行强制转换
        //根据bean的名称获取bean对象
        UserMapper userMapper1 = (UserMapper) applicationContext.getBean("userMapper");
        //根据bean的类型获取bean对象
        UserMapper userMapper2 = applicationContext.getBean(UserMapper.class);
        //根据bean的名称和类型获取bean对象
        UserMapper userMapper3 = applicationContext.getBean("userMapper", UserMapper.class);
    }
}

Bean的作用域

  • IOC容器中获取出来的bean对象默认是单例的只有一个

Spring支持五种作用域,后三种在web环境才生效

作用域说明
singleton单例,默认值,一个IOC容器中只有一个实例
prototype原型,每次获取都是新的实例
request每一次请求都会创建一个新的实例
session每一个会话都会创建一个新的实例
application全局唯一实例

@Scope("prototype")
@Lazy
@PostMaping("/depts")
public class User {

}

注意

  • 默认singletonbean,在容器启动时被创建,可以使用@Lazy注解懒加载,在第一次使用时才创建
  • prototype作用域的bean,每次获取都是新的实例,不会被缓存,每次获取都是新的实例
  • 在实际开发中,绝大部分的bean都是单例的,也就是说绝大部分的bean不需要配置scope作用域

第三方bean

如果要管理的bean对象来自第三方(不是自己定义的),是无法用@Component注解进行标注的,此时需要使用@Bean 注解进行标注,用来管理bean对象。

方法一 在启动类中声明bean对象 (不建议)


@SpringBootApplication
public class SpringbootApplication {
    @Bean//将方法执行的返回值交给Ioc容器管理,成为Ioc容器中的bean对象
    public SaxBean saxBean() {
        return new SaxBean();
    }

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

方法二 声明一个配置类,使用@Configuration注解进行标注(标注为一个配置类),然后在配置类中声明bean对象


@Configuration
public class MyConfig {
    @Bean
    //可以通过@bean注解的name或value属性来声明bean的名字 但一般不指定默认为方法名
    @Bean(name = "saxBean", value = "saxBean")
    public SaxBean saxBean() {
        return new SaxBean();
    }

    //如果该第三方的bean对象需要注入其他bean对像可以直接写在方法形参中 当该bean对象被创建时,会自动注入到方法形参中
    @Bean
    public SaxBean saxBean(User user) {
        saxBean.setUser(user);
        return new SaxBean();
    }
}

SpringBoot起步依赖

SpringBoot的起步依赖主要根据Maven的依赖传递特性来实现

SpringBoot自动配置

SpringBoot项目的自动配置就是当项目启动后,一些配置类、bean对象就自动存入了IOC容器中,不需要我们手动去声明,从而简化了开发。

方案一 通过@ComponentScan注解进行组件扫描 该方式使用繁琐


@SpringBootApplication
@ComponentScan({"com.saxena.vaibhav"})
public class Application {
	---
}

方案二 在启动类中使用@import注解j进行导入,导入的类会被Spring加载到IOC容器中,导入形式主要有以下几种

1. 导入普通类


@SpringBootApplication
@Import({com.springboot.Pojo.Cat.class})
public class Application {

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

}

2. 导入配置类


@SpringBootApplication
@Import({com.springboot.config.MyConfig.class})
public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

3. 导入是实现类

//实现类

public class UserServiceImpl implements UserService {
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.springboot.service.impl.UserServiceImpl"};
    }
}

@SpringBootApplication
@Import({com.springboot.service.impl.UserServiceImpl.class})
public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

ImportSelector接口

ImportSelectorSpring 框架中的一个接口,主要用于动态导入配置类或组件。它的作用可以总结如下:

  1. 动态选择需要导入的类 实现 ImportSelector 接口的类可以通过重写 selectImports 方法,在运行时动态决定需要导入的类。这些类会被 Spring 容器加载并管理。
  2. 基于元数据的条件化导入 selectImports 方法接收一个 AnnotationMetadata 参数,该参数包含了当前标注了 @Import 的类的元数据信息。通过解析这些元数据,可以根据条件动态选择需要导入的类。
    1. 增强配置灵活性 通过 ImportSelector,开发者可以在不修改代码的情况下,根据环境、配置或其他条件动态调整 Spring 容器中加载的 Bean

方案三 让第三方组件来声明自己要导入哪些类

第三方组件中一般都会使用@EnableXXX注解,封装@Import注解,在将但三方组件加入到项目中时只需要使用该注解就能快速注入bean对象。

//1. 使用ImportSelector的实现类返回要导入哪些类
package com.springboot.Pojo;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.springboot.Pojo.Cat"};
    }
}

//2.在自定义注解中使用`@Import`注解导入实现类
ackage com.springboot.Pojo;

import org.springframework.context.annotation.Import;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)//注解生命周期 (运行时)
@Target(java.lang.annotation.ElementType.TYPE) //注解作用位置(类、接口)
@Import(MyImportSelector.class)
public @interface EnableMyImport {
}

//在启动类中使用自定义注解
package com.springboot;

@SpringBootApplication
@EnableMyImport
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
上次更新 2025/3/20 21:35:51