SpringBoot 原理专题

优先级与打包

  1. 命令行参数
  2. 系统环境
  3. properties
  4. yml
  5. yaml

打包插件

xml 复制代码
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>${spring-boot.version}</version>
    <configuration>
        <mainClass>com.example.DemoApplication</mainClass>
        <skip>true</skip>
    </configuration>
    <executions>
        <execution>
            <id>repackage</id>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

打包后运行,带额外参数

bash 复制代码
java -Dserver.port=9000 -jar dd.jar

Bean 作用域

作用域 说明
singleton 容器内同 名称 的 bean 只有一个实例(单例)(默认)
prototype 每次使用该 bean 时会创建新的实例(非单例/多例)
request 每个请求范围内会创建新的实例(web环境中,了解)
session 每个会话范围内会创建新的实例(web环境中,了解)
application 每个应用范围内会创建新的实例(web环境中,了解)

配置 Scope 注解,选择单例

  • Lazy 表示延迟加载,默认是启动时加载,配置后表示延迟到第一次使用加载
  • SCOPE_SINGLETON 单例
  • SCOPE_PROTOTYPE 非单例
java 复制代码
@Lazy
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
@RestController
public class BasicController {}

注意:

  1. 单例是无状态的,多例是有状态的。
  2. 单例是节约资源,提升性能
  3. 单例bean:如果是无状态的bean,内部不保存任何状态信息,则是线程安全的。
  4. 单例bean:如果是有状态的bean,内部会保存状态信息,多个线程会同时操作该bean时,可能会出现数据不一致的问题,这样的bean则是线程不安全的。

起步依赖

依赖,具有传递性。

自动配置

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

比如:引入了redis依赖,可以直接注入Redis使用。

实现方案一

加入另一个项目的依赖,引入依赖,并在主类上加上包扫描,扫描该依赖的包,不推荐,原因是操作麻烦+性能低

实现方案二

类不需要加任何注解,直接使用 Import 导入,或者使用Imort 导入一个配置类。

java 复制代码
@Import(TokenService.class)
@SpringBootApplication
public class DemoApplication {

配置类代码

java 复制代码
public class MyImportSelector implements ImportSelector {

    // 返回多个类的全限定命名
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.example.aop.RecordTimeAspect2"};
    }
}

实现方案三:加注解的方式,最实用

java 复制代码
// 核心还是用方式二
@Import(MyImportSelector.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableHeaderConfig {
}

条件判断 / 自动配置

有时候我们经常需要判断该类应不应该注入到IOC容器中。

  • 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring IOC容器中。

  • 位置:方法、类

  • @Conditional 本身是一个父注解,派生出大量的子注解:

  • @ConditionalOnClass:判断环境中是否有对应字节码文件,才注册bean到IOC容器。

  • @ConditionalOnMissingBean:判断环境中没有对应的bean(类型 或 名称) ,才注册bean到IOC容器。

  • @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

java 复制代码
@Bean
// 判断环境中是否存在io.jsonwebtoken.Jwts,如果有就创建该Bean
@ConditionalOnClass(name = "io.jsonwebtoken.Jwts")
// 判断环境中是否存在该类,如果没有就创建该Bean
@ConditionalOnMissingBean
// 判断属性值是否为true,在配置文件中
@ConditionalOnProperty(name = "enable", havingValue = "true")
public RecordTimeAspect2 recordTimeAspect2(){
    return new RecordTimeAspect2();
}

自己定义自动配置类的核心是什么? 如何完成自动配置?

  1. 定义自动配置类
  2. 将自动配置类配置在 META-INF/spring/
  3. org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中

自定义Starter

需求:自定义aliyun-oss-spring-boot-starter,完成阿里云OSS操作工具类 AliyunOSSOperator 的自动配置。

目标:引入起步依赖引入之后,要想使用阿里云OSS,注入 AliyunOSSOperator 直接使用即可。

步骤:

  1. 创建aliyun-oss-spring-boot-starter模块
  2. 创建aliyun-oss-spring-boot-autoconfigure模块,在starter中引入该模块
  3. 在aliyun-oss-spring-boot-autoconfigure模块中的定义自动配置功能,并定义自动配置文件 META-INF/spring/xxxx.imports

注意:选择一个版本,无需要选依赖

只需要依赖是 spring-boot-starter 就可以。

java 复制代码
@Configuration
@EnableConfigurationProperties(OSSProperties.class) // 引入配置类
public class OSSConfig {

    @Bean
    public OSS endpoint(OSSProperties ossProperties) {
        DefaultCredentialProvider defaultCredentialProvider =
                new DefaultCredentialProvider(ossProperties.getAccessKeyId(), ossProperties.getSecretAccessKey());
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        return OSSClientBuilder.create()
                .endpoint("https://" + ossProperties.getEndpoint())
                .credentialsProvider(defaultCredentialProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(extractRegion(ossProperties.getEndpoint()))
                .build();
    }

    /**
     * 获取 region
     */
    private String extractRegion(String endpoint) {
        if (endpoint == null) return null;
        int start = endpoint.indexOf("oss-");
        int end = endpoint.indexOf(".aliyuncs.com");
        if (start == -1 || end == -1 || start + 4 >= end)
            throw new IllegalArgumentException("Invalid endpoint: " + endpoint);
        return endpoint.substring(start + 4, end);
    }

}
java 复制代码
@Data
@ConfigurationProperties(prefix = "aliun.oss")
public class OSSProperties {

    private String endpoint;
    private String accessKeyId;
    private String secretAccessKey;
}
相关推荐
咩咩啃树皮13 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚14 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白15 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司16 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地17 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415917 小时前
TCP超时重传机制是为了解决什么问题?
java
莫逸风19 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
隔窗听雨眠19 小时前
Spring Boot在云原生时代的编程范式革新研究
spring boot·后端·云原生
z1234567898620 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin52112320 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python