SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解

简介:我们一直在说基于SpringBoot开发简单、快捷,但是总是不太清楚为什么会有这样的便利,对于开发人员来说我们不仅要知其然,还要知其所以然,这篇文章就是说明SpringBoot的底层原理,让读者对SpringBoot底层的运行机制有深一层的了解。

目录

1、起步依赖

2、自动配置

2.1 自动配置原理

2.2 @Conditional注解

2.3 案例(自定义starter)

3、总结


1、起步依赖

  • SpringBoot 通过提供众多起步依赖降低项目依赖的复杂度。起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。很多起步依赖的命名都暗示了它们提供的某种或某类功能。

2、自动配置

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

2.1 自动配置原理

  • 方案一:@ComponentScan 组件扫描
图 2.1-1 添加第三方地址
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第1张图片
上图是在当前项目的pom.xml配置文件中添加第三方项目的地址,从而可以在当前项目引用第三方项目资源。
图 2.1-2 @ComponentScan()注解 
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第2张图片

上图中的 @ComponentScan()注解定义在当前项目启动类中,当前项目启动时会自动扫描参数中包名的所有bean对象并将其存储到IOC容器中。

优势:能全面的扫描的包内的所有bean对象。

缺点:性能慢,开发中不是所有的bean都需要(主流开发不使用)。

  • 方案二:@import导入。使用@import导入的类会被加载到IOC容器中,导入的形式主要有以下几种:
    • 导入 普通类
    • 导入 配置类
    • 导入 ImportSelector 接口实现类
    • @EnableXxxx注解,封装@import注解
图 2.1-3  添加第三方项目地址
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第3张图片
图片中展示的是在本项目的pom.xml文件中添加第三方项目的地址依赖,这样就可以在本项目中使用第三方的资源。(备注:下面几种,第三方bean对象导入IOC容器中,都是在第三方项目的地址已经在pom.xml文件中的基础上
图 2.1-4 import 导入普通类、配置类
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第4张图片
上图中是通过@Import() 注解(注解中的参数为被调用第三方资源的类名称),调用第三方项目的资源且将被调用的资源对象存储到IOC容器中。
图 2.1-5 导入 ImportSelector 接口实现类
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第5张图片

上图是在被调用第三方项目中创建一个 ImportSelector 接口的实现类  MyImportSelector ,实现类返回值为允许被调用bean对象资源的全类名。

图 2.1-6 导入 ImportSelector 接口实现类
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第6张图片

上图是在当前项目启动类中通过 @Import 注解,将第三方项目的接口实现类(图 2.1-5)MyImportSelector导入。

图 2.1-7 使用@EnableXxxx注解
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第7张图片
上图是在图2.1-6的基础上,在第三方资源项目中创建 EnableHeaderConfig注解并且使用 @Import()注解引用第三方资源项目的接口实现类  MyImportSelector,这样开发者直接在当前开发项目中直接使用 EnableHeaderConfig注解就可以了。  这也是当前开发工作中的主流方式。

2.2 @Conditional注解

图 2.2-1 使用@Conditional注解
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第8张图片
上图是 @Conditional的作用,他是一个父级注解,开发中最主要的就是三个字注解,需要掌握这三个子注解的使用方法。
图 2.2-2 使用@Conditional 相关子注解
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第9张图片

上图中在第三方资源项目中的 HeaderConfig类中,使用了三个注解;

  1. @ConditionalOnMissingBean //不存在该类型的bean,才会将该bean加入到IOC容器中 -- 指定类型(value属性) 或 名称(name属性)
  2. @ConditionalOnClass(name = "io.jsonwebtoken.Jwts") //环境中存在指定的这个类,才会将该bean加入IOC容器中
  3. @ConditionalOnProperty() //配置文件中存在指定的属性与值,才会将该bean加入到IOC容器中

开发者可以根据需要,自主在第三方资源项目中选择使用这三个注解中适用的,方便将注解对应的bean对象放进当前引用的第三方资源

2.3 案例(自定义starter)

在实际的开发过程中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中,一般会把这些公共组件封装为SpringBoot的starter。

下面是在IDEA项目中创建一个自定义starter依赖,关于操作阿里云OSS的操作工具类。

图 2.3-1 自定义starter
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第10张图片
图片中是创建一个阿里云OSS操作工具类的项目依赖步骤,分为依赖管理功能、自动配置功能。
图 2.3-2 创建starter
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第11张图片
图 2.3-3 创建autoconfigure模块
SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第12张图片
上图中是在当前项目中创建autoconfigure模块,并且只保留pom.xml、iml、src文件,其他的删除掉。

之后是在创建的autoconfigure模块中的pom.xml文件中添加阿里云的相关依赖(代码如下)

        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.projectlombok
            lombok
            true
        

        
        
        
            com.aliyun.oss
            aliyun-sdk-oss
            3.15.1
        
        
            javax.xml.bind
            jaxb-api
            2.3.1
        
        
            javax.activation
            activation
            1.1.1
        

只有在autoconfigure模块中的pom.xml文件中添加依赖后,才能编写代码。

  1. 接下来是去创建 AliOSSProperties 类,这是一个属性类,用于记录阿里云的秘钥等数据(代码如下)
    package com.aliyun.oss;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @Data
    @ConfigurationProperties(prefix = "aliyun.oss")
    public class AliOSSProperties {
        private String endpoint;
        private String accessKeyId;
        private String accessKeySecret;
        private String bucketName;
    }
    
  2. 之后是创建阿里云OSS工具类  AliOSSUtils,这个类的功能是将文件上传至阿里云中(代码如下)
    package com.aliyun.oss;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.UUID;
    
    /**
     * 阿里云 OSS 工具类
     */
    public class AliOSSUtils {
    
    //    @Value("${aliyun.oss.endpoint}")
    //    private String endpoint ;
    //    @Value("${aliyun.oss.accessKeyId}")
    //    private String accessKeyId ;
    //    @Value("${aliyun.oss.accessKeySecret}")
    //    private String accessKeySecret ;
    //    @Value("${aliyun.oss.bucketName}")
    //    private String bucketName ;
    
        private AliOSSProperties aliOSSProperties;
    
        public AliOSSProperties getAliOSSProperties() {
            return aliOSSProperties;
        }
    
        public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
            this.aliOSSProperties = aliOSSProperties;
        }
    
        /**
         * 实现上传图片到OSS
         */
        public String upload(MultipartFile file) throws IOException {
            //获取阿里云OSS参数
            String endpoint = aliOSSProperties.getEndpoint();
            String accessKeyId = aliOSSProperties.getAccessKeyId();
            String accessKeySecret = aliOSSProperties.getAccessKeySecret();
            String bucketName = aliOSSProperties.getBucketName();
    
            // 获取上传的文件的输入流
            InputStream inputStream = file.getInputStream();
    
            // 避免文件覆盖
            String originalFilename = file.getOriginalFilename();
            String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
    
            //上传文件到 OSS
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.putObject(bucketName, fileName, inputStream);
    
            //文件访问路径
            String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
            // 关闭ossClient
            ossClient.shutdown();
            return url;// 把上传到oss的路径返回
        }
    
    }
    
  3. 最后是创建一个 AliOSSConfiguration 配置类,用于将阿里云的 AliOSSUtils 对象存放如IOC容器中。
    package com.aliyun.oss;
    
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @EnableConfigurationProperties(AliOSSProperties.class)
    public class AliOSSConfiguration {
    
        @Bean
        public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){
            AliOSSUtils aliOSSUtils = new AliOSSUtils();
            aliOSSUtils.setAliOSSProperties(aliOSSProperties);
            return aliOSSUtils;
        }
    }
    

接下来定义配置文件,用于IDEA找到AliOSSConfiguration 配置类对象(如下图)

SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解_第13张图片

3、总结

以上就是关于SpringBoot原理(@Conditional) — 三种自动配置方法、步骤详解。小编初次接触的时候还是觉得比较绕的,后面自己多思考动手还思维导图,总算是理解并且记住了。

你可能感兴趣的:(JAVA语言,spring,boot,java,spring)