【SpringBoot】 @Conditional 注解

SpringBoot @Condition 注解

简介

Conditional作用就是当你注册bean时,可以对这个bean添加一定的自定义条件,当满足这个条件时,注册这个bean,否则不注册。

开始

新建User.java

public class User {
}

新建一个UserConfig.java 用来注入bean。

@Configuration
public class UserConfig {

    @Bean
    public User userBean(){
        return new User();
    }
}

修改启动类,我们在启动的时候去获取userBean

@SpringBootApplication
public class BootConditionApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =  SpringApplication.run(BootConditionApplication.class, args);
        User user = (User) context.getBean("userBean");
        System.out.println(user);
    }
}

如果userBean在Spring容器里面,我们就可以通过上下文可以获取到user 对象.
在以上的代码中,我们是可以获取到bean哈,控制台打印结果如下所示:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.1.RELEASE)

2023-07-03 10:19:47.362  INFO 2580 --- [           main] x.b.condition.BootConditionApplication   : Starting BootConditionApplication on ZJZL-20210402GJ with PID 2580 (F:\idea-project\xy-integration-middleware\boot\boot-condition\target\classes started by Administrator in F:\idea-project\xy-integration-middleware)
2023-07-03 10:19:47.391  INFO 2580 --- [           main] x.b.condition.BootConditionApplication   : No active profile set, falling back to default profiles: default
2023-07-03 10:19:49.206  INFO 2580 --- [           main] x.b.condition.BootConditionApplication   : Started BootConditionApplication in 3.789 seconds (JVM running for 10.207)
xy.boot.condition.entity.User@15bcf458

简单的场景实现

要求:我们要求userBean 在引入fastjson的情况下,才进行注入,反之不进行注入。

Conditional源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}

可以看到value里面的值类型只定义了一个Class类型的数组 ,要求为Condition的泛型。

Condition接口

这个接口只定义了一个方法名为matches,返回值为一个boolean,这个时候我们不难猜出,
当Conditional注解中的值为true则会执行标注的方法,这里我们再写一个类实现Condition接口 ,
可以看到默认的返回值是为 false。

/**
ConditionContext:这个对象是个上下文对象,可以用它获取环境,ioc以及类加载器

AnnotatedtypeMetadata:注解元对象,可以获得注解中传入的值
*/
@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

通过以上代码,我们可以实现condition接口,实现自己自定义的方式。

自定义condition

public class ClassOnCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        // 定义一个布尔值
        boolean flag;
        try {
            // 通过反射找到fastjson的类
            Class<?> aClass = Class.forName("com.alibaba.fastjson.JSON");
            // 找到了则返回true
            flag = true;
        } catch (ClassNotFoundException e) {
            // 找不到则返回false
            flag = false;
        }
        return flag;
    }
}

在UserConfig.java 中加入Conditional注解,如下所示:

@Configuration
public class UserConfig {

    @Bean
    @Conditional(ClassOnCondition.class)
    public User user(){
        return new User();
    }
}

测试

未加入依赖

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.1.RELEASE)

2023-07-03 10:31:22.175  INFO 7724 --- [           main] x.b.condition.BootConditionApplication   : Starting BootConditionApplication on ZJZL-20210402GJ with PID 7724 (F:\idea-project\xy-integration-middleware\boot\boot-condition\target\classes started by Administrator in F:\idea-project\xy-integration-middleware)
2023-07-03 10:31:22.193  INFO 7724 --- [           main] x.b.condition.BootConditionApplication   : No active profile set, falling back to default profiles: default
2023-07-03 10:31:23.791  INFO 7724 --- [           main] x.b.condition.BootConditionApplication   : Started BootConditionApplication in 2.88 seconds (JVM running for 6.428)
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userBean' available
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:772)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1221)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:294)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
	at xy.boot.condition.BootConditionApplication.main(BootConditionApplication.java:13)
Disconnected from the target VM, address: '127.0.0.1:63662', transport: 'socket'

加入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.1.RELEASE)

2023-07-03 10:33:00.091  INFO 15508 --- [           main] x.b.condition.BootConditionApplication   : Starting BootConditionApplication on ZJZL-20210402GJ with PID 15508 (F:\idea-project\xy-integration-middleware\boot\boot-condition\target\classes started by Administrator in F:\idea-project\xy-integration-middleware)
2023-07-03 10:33:00.099  INFO 15508 --- [           main] x.b.condition.BootConditionApplication   : No active profile set, falling back to default profiles: default
2023-07-03 10:33:01.458  INFO 15508 --- [           main] x.b.condition.BootConditionApplication   : Started BootConditionApplication in 2.409 seconds (JVM running for 6.339)
xy.boot.condition.entity.User@60afd40d
Disconnected from the target VM, address: '127.0.0.1:63765', transport: 'socket'

优化

我们可以在自定义一个注解 ConditionalOnClass

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassOnCondition.class)
public @interface ConditionalOnClass {
    String[] value();
}

修改ClassOnCondition

public class ClassOnCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        // 定义一个布尔值
        boolean flag;
        try {
            // 通过注解名获取其中的值
            Map<String, Object> map = annotatedTypeMetadata.getAnnotationAttributes(ConditionalOnClass.class.getName());
            // 获取value的值
            String[] classNames = (String[]) map.get("value");
            for (String className : classNames) {
                Class<?> aClass = Class.forName(className);
            }
            flag = true;
        } catch (ClassNotFoundException e) {
            // 找不到则返回false
            flag = false;
        }
        return flag;
    }
}

修改UserConfig

@Configuration
public class UserConfig {

    @Bean
    @ConditionalOnClass("com.alibaba.fastjson.JSON")
    public User user(){
        return new User();
    }
}

修改完成后,重新启动,我们会发现跟上面测试结果是一样子的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值