• SpringBoot自动配置及自定义starter


    @Import注解用法

    @Import是Spring基于 Java 注解配置的主要组成部分。接收一个Class类数组,把类加入Spring IOC容器。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
        Class<?>[] value();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    方式一:class类数组

    • 创建ClassA类
    public class ClassA {
    
        public void print(){
            System.out.println("this is ClassA !!!");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 通过@Import引入ClassA
    @Import({ClassA.class})
    @Configuration
    public class ImportConfig {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • @Autowired注入ClassA测试
    @SpringBootTest
    class ImportApplicationTests {
        
        @Autowired
        ClassA classA;
    
        @Test
        void contextLoads() {
            this.classA.print();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出:this is ClassA !!!

    方式二:实现ImportSelector接口

    • 创建ClassB类
    public class ClassB {
        
        public void print(){
            System.out.println("this is ClassB !!!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 创建TestImportSelector类实现ImportSelector接口,返回包含ClassB类的数组
    public class TestImportSelector implements ImportSelector {
        
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return new String[]{"com.example.xx.xx.ClassB"};
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • @Import引入TestImportSelector.class
    @Import({TestImportSelector.class})
    @Configuration
    public class ImportConfig {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • @Autowired注入ClassB测试
    @SpringBootTest
    class ImportApplicationTests {
        
        @Autowired
        ClassB classB;
        
        @Test
        void contextLoads() {
            this.classB.print();
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出:this is ClassB !!!

    方式三:实现ImportBeanDefinitionRegistrar接口

    • 创建ClassC类
    public class ClassC {
        public void print(){
            System.out.println("this is ClassC !!!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 创建ImportBean类实现ImportBeanDefinitionRegistrar接口
    public class ImportBean implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            RootBeanDefinition root = new RootBeanDefinition(ClassC.class);
            registry.registerBeanDefinition("classC", root);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • @Import引入ImportBean类
    @Import({ImportBean.class})
    @Configuration
    public class ImportConfig {
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • @Autowired注入ClassC测试
    @SpringBootTest
    class ImportApplicationTests {
    
        @Autowired
        ClassC classC;
    
        @Test
        void contextLoads() {
            this.classC.print();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出:this is ClassC !!!

    三种方式可以同时用

    @Import({ClassA.class, TestImportSelector.class, ImportBean.class})
    @Configuration
    public class ImportConfig {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    class ImportApplicationTests {
    
        @Autowired
        ClassA classA;
        @Autowired
        ClassB classB;
        @Autowired
        ClassC classC;
    
        @Test
        void contextLoads() {
            this.classA.print();
            this.classB.print();
            this.classC.print();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    输出:
    this is ClassA !!!
    this is ClassB !!!
    this is ClassC !!!

    自动配置原理

    • @Import引入AutoConfigurationImportSelector.class

    在这里插入图片描述

    • selectImports()方法

    在这里插入图片描述

    • getAutoConfigurationEntry()方法

    在这里插入图片描述

    • loadFactoryNames()方法

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    最终读取的是META-INF目录下的spring.factories文件和spring-autoconfigure-metadata.properties配置文件。
    在这里插入图片描述

    自定义starter

    1、创建一个SpringBoot项目
    2、编写StarterDemo.java

    public class StarterDemo {
    
        private String starterName;
    
        public StarterDemo(String starterName) {
            this.starterName = starterName;
        }
    
        public String getStarterName() {
            return starterName;
        }
    
        public void setStarterName(String starterName) {
            this.starterName = starterName;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3、编写StarterConfig配置类

    public class StarterConfig {
    
        @Value("${starter.name}")
        private String starterName;
    
        @Bean
        public StarterDemo starterDemo() {
            return new StarterDemo(starterName);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4、在resource目录下创建一个META-INF文件夹并新建spring.factories文件

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.mystarter.config.StarterConfig
    
    • 1

    5、在另外的SpringBoot项目引入my-starter,并创建配置属性starter.name

    <dependency>
      <groupId>com.examplegroupId>
      <artifactId>my-starterartifactId>
      <version>0.0.1-SNAPSHOTversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    starter:
      name: my-starter
    
    • 1
    • 2

    6、测试

    @SpringBootTest
    class MyApplicationTests {
    
        @Autowired
        private StarterDemo starterDemo;
    
        @Test
        void contextLoads() {
            System.out.println(starterDemo.getStarterName());
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出:my-starter

  • 相关阅读:
    FVP和Juno平台的Memory Layout介绍
    Android studio初次运行项目报错
    Docker-Compose安装、卸载、使用详解
    阿里强推:Java程序设计基于JDK11零基础学Java笔记
    【后端面经-数据库】Redis数据结构和底层数据类型
    隧道技术的三种应用场景(IPv6,多播,VPN)
    【求助】西门子S7-200PLC定时中断+数据归档的使用
    4721. 排队
    ConcurrentLinkedQueue解析
    【flask进阶】Flask实现自定义分页(python web通用)
  • 原文地址:https://blog.csdn.net/qq_36700462/article/details/126452644