SpringBoot自定义Starter(二十四)下

简介: 三. 自定义Starter 深入理解三.一 pom.xml 中添加依赖三.二 定义一个接口和两个实现类三.三 定义实现类起作用的条件三.四 让条件被管控三.五 测试三.六 Profile 多环境配置

三. 自定义Starter 深入理解

自定义的Starter 能够起作用,条件注解起了很大的作用.

演示一下条件注解的使用.

仍然使用 刚才的自定义 Starter

三.一 pom.xml 中添加依赖

   <dependencies>
        <!--添加自动配置的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>
        <!--添加配置文件引用的依赖信息-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.2.2.RELEASE</version>
            <optional>true</optional>
        </dependency>
        <!--添加 spring-context依赖, 对应的 2.2.2 版本-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
    </dependencies>

三.二 定义一个接口和两个实现类

定义 Animal 接口

package top.yueshushu.condition;
/**
 * @ClassName:Animal
 * @Description 定义一个动物的接口
 * @Author zk_yjl
 * @Date 2021/10/25 20:48
 * @Version 1.0
 * @Since 1.0
 **/
public interface Animal {
    /**
     * 定义一个声音的接口
     * @date 2021/10/25 20:49
     * @author zk_yjl
     * @param
     * @return void
     */
    public void voice();
}

有两个实现类, 一个是 Cat 一个是 Dog

Cat.java

package top.yueshushu.condition;
/**
 * @ClassName:Cat
 * @Description TODO
 * @Author zk_yjl
 * @Date 2021/10/25 20:50
 * @Version 1.0
 * @Since 1.0
 **/
public class Cat implements Animal {
    @Override
    public void voice() {
        System.out.println(">>>喵喵喵");
    }
}

Dog.java

package top.yueshushu.condition;
/**
 * @ClassName:Dog
 * @Description 狗的实现类
 * @Author zk_yjl
 * @Date 2021/10/25 20:49
 * @Version 1.0
 * @Since 1.0
 **/
public class Dog implements Animal {
    @Override
    public void voice() {
        System.out.println(">>>>汪汪汪");
    }
}

三.三 定义实现类起作用的条件

Animal 接口有两个实现类 Cat, Dog 在使用中,要使用哪一个呢?

总不能

@Resource("cat")
private Animal animal
@Resource("dog")
private Animal animal

这样肯定是不行的。

可以定义条件, 当Cat 的条件满足时,就用 Cat 的实现类, 当 Dog 的条件满足时,就用 Dog 的实现类

三.三.一 Cat 实现条件 CatCondition

package top.yueshushu.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
 * @ClassName:CatCondition
 * @Description TODO
 * @Author zk_yjl
 * @Date 2021/10/25 20:53
 * @Version 1.0
 * @Since 1.0
 **/
// 实现 Condition 接口
public class CatCondition implements Condition {
   @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String animal = context.getEnvironment().getProperty("animal");
        //为空属性,不创建
        if(StringUtils.isEmpty(animal)){
            return false;
        }
        return "Cat".equalsIgnoreCase(animal);
    }
}

三.三.二 Dog 实现条件 DogCondition

package top.yueshushu.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;
/**
 * @ClassName:DogCondition
 * @Description TODO
 * @Author zk_yjl
 * @Date 2021/10/25 20:51
 * @Version 1.0
 * @Since 1.0
 **/
public class DogCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //没有获取到这个属性时,走 Dog 
        String animal = context.getEnvironment().getProperty("animal");
        if(StringUtils.isEmpty(animal)){
            return true;
        }
        return "Dog".equalsIgnoreCase(animal);
    }
}

三.四 让条件被管控

现在有 Cat 的条件,也有 Dog 的条件。


但这两个条件,只是实现了 Condition 接口, 并没有添加形如 @Component @Configuration 等类似的注解

说明,这两个条件,还没有办法被SpringBoot 管控到.

JavaAnimalConfig 管控条件

package top.yueshushu.condition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
 * @ClassName:JavaAnimalConfig
 * @Description TODO
 * @Author zk_yjl
 * @Date 2021/10/25 20:54
 * @Version 1.0
 * @Since 1.0
 **/
@Configuration
public class JavaAnimalConfig {
    /**
    条件符合时,创建
     */
    @Bean("animal")
    @Conditional(DogCondition.class)
    Animal dog(){
        return new Dog();
    }
    /**
     条件符合时,创建
     */
    @Bean("animal")
    @Conditional(CatCondition.class)
    Animal cat(){
        return new Cat();
    }
}

两者创建的,bean 都是 animal

三.五 测试

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        //ctx.getEnvironment().getSystemProperties().put("animal", "Cat");
       // ctx.getEnvironment().getSystemProperties().put("animal", "Dog");
        //  ctx.getEnvironment().getSystemProperties().put("animal", "YJL");
        ctx.register(JavaAnimalConfig.class);
        ctx.refresh();
        Animal animal = (Animal) ctx.getBean("animal");
        animal.voice();
    }
}

设置环境变量值的信息, 都去掉, 会生成默认的 Dog

当使用 Cat 时, 会打印 Cat 的实现类

当使用 Dog 时,会打印 Dog 的实现类

当使用 YJL 时, 因为都不符合,所以创建不了相应的 Bean

1.png也可以将这个自定义的Starter clean install 安装后, StarterApply 引用

@RunWith(SpringRunner.class)
@SpringBootTest
public class StarterTest {
    @Autowired
    private UserPropertiesService userPropertiesService;
    @Test
    public void starterPrintlnTest(){
        String message = userPropertiesService.println();
        System.out.println("Apply项目输出信息:"+message);
    }
   // 运行测试一下 
    @Test
    public void animalJavaTes(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.getEnvironment().getSystemProperties().put("animal", "Cat");
        ctx.register(JavaAnimalConfig.class);
        ctx.refresh();
        Animal animal = (Animal) ctx.getBean("animal");
        animal.voice();
    }
}

发现,也是相同的测试结果.

三.六 Profile 多环境配置

在多环境配置时,我们使用到了 Profile

在 JavaAnimalConfig 里面,

public class JavaAnimalConfig {
    /**
    条件符合时,创建
     */
    @Bean("animal")
    @Conditional(DogCondition.class)
    Animal dog(){
        return new Dog();
    }
    /**
     条件符合时,创建
     */
    @Bean("animal")
    @Conditional(CatCondition.class)
    Animal cat(){
        return new Cat();
    }
}

我们定义了 DogCondition, 能不能将这个换成 Profile 呢? 这样就不用根据环境变量的值来确定实例化哪一个实现了,而是根据环境配置来实现化具体的实现.

@Configuration
public class JavaAnimalConfig {
    /**
    条件符合时,创建
     */
    @Bean("animal")
  //  @Conditional(DogCondition.class)  不使用
    @Profile("Dog") //触发条件
    Animal dog(){
        return new Dog();
    }
    /**
     条件符合时,创建
     */
    @Bean("animal")
    //@Conditional(CatCondition.class)
    @Profile("Cat") //触发条件
    Animal cat(){
        return new Cat();
    }
}

进行测试

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        //ctx.getEnvironment().getSystemProperties().put("animal", "Cat");
       // ctx.getEnvironment().getSystemProperties().put("animal", "Dog");
       // ctx.getEnvironment().getSystemProperties().put("animal", "YJL");
       // ctx.getEnvironment().setActiveProfiles("Dog");
        //ctx.getEnvironment().setActiveProfiles("Cat");
       // ctx.getEnvironment().setActiveProfiles("YJL");
        ctx.register(JavaAnimalConfig.class);
        ctx.refresh();
        Animal animal = (Animal) ctx.getBean("animal");
        animal.voice();
    }
}

当启用 Dog 时, 实现的是 Dog

当启用的是 Cat 时,实现的是 Cat 实现

当启用的是 YJL 时,会报异常信息。与上面的测试结果一致.

也同样可以在 StarterTest 类中进行测试,

 @Test
    public void animalJavaTes(){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        //ctx.getEnvironment().getSystemProperties().put("animal", "Cat");
        // ctx.getEnvironment().getSystemProperties().put("animal", "Dog");
        // ctx.getEnvironment().getSystemProperties().put("animal", "YJL");
         ctx.getEnvironment().setActiveProfiles("Dog");
        //ctx.getEnvironment().setActiveProfiles("Cat");
        // ctx.getEnvironment().setActiveProfiles("YJL");
        ctx.register(JavaAnimalConfig.class);
        ctx.refresh();
        Animal animal = (Animal) ctx.getBean("animal");
        animal.voice();
    }

测试结果,也是一样的。

但如果将 setActiveProfiles 都去掉,在 application.yml 中进行设置

2.png

是不可以的。 还是会报错误

3.png


相关文章
32SpringBoot自定义Starter
32SpringBoot自定义Starter
98 0
32SpringBoot自定义Starter
|
架构师 NoSQL Java
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
|
设计模式 Java 机器人
SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter
SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter
|
8月前
|
Java Maven 开发者
编写SpringBoot的自定义starter包
通过本文的介绍,我们详细讲解了如何创建一个Spring Boot自定义Starter包,包括自动配置类、配置属性类、`spring.factories`文件的创建和配置。通过自定义Starter,可以有效地复用公共配置和组件,提高开发效率。希望本文能帮助您更好地理解和应用Spring Boot自定义Starter,在实际项目中灵活使用这一强大的功能。
614 17
|
9月前
|
JavaScript Java 程序员
SpringBoot自动配置及自定义Starter
Java程序员依赖Spring框架简化开发,但复杂的配置文件增加了负担。SpringBoot以“约定大于配置”理念简化了这一过程,通过引入各种Starter并加载默认配置,几乎做到开箱即用。
353 10
SpringBoot自动配置及自定义Starter
|
10月前
|
Java 数据库连接 Maven
最新版 | SpringBoot3如何自定义starter(面试常考)
在Spring Boot中,starter是一种特殊的依赖,帮助开发人员快速引入和配置特定功能模块。自定义starter可以封装一组特定功能的依赖和配置,简化项目中的功能引入。其主要优点包括模块化、简化配置、提高代码复用性和实现特定功能。常见的应用场景有短信发送模块、AOP日志切面、分布式ID生成等。通过创建autoconfigure和starter两个Maven工程,并编写自动配置类及必要的配置文件,可以实现一个自定义starter。最后在测试项目中验证其有效性。这种方式使开发者能够更便捷地管理和维护代码,提升开发效率。
1302 1
最新版 | SpringBoot3如何自定义starter(面试常考)
|
IDE Java Maven
SpringBoot自定义starter及自动配置
SpringBoot自定义starter及自动配置
|
Java Maven 开发者
Spring Boot中的自定义Starter开发
Spring Boot中的自定义Starter开发
|
Java Maven Spring
Spring Boot中的自定义Starter开发
Spring Boot中的自定义Starter开发
|
Java 数据库连接 Maven
SpringBoot【付诸实践 01】SpringBoot自定义starter保姆级教程(说明+源码+配置+测试)
SpringBoot【付诸实践 01】SpringBoot自定义starter保姆级教程(说明+源码+配置+测试)
168 1

热门文章

最新文章