@Conditional 条件装配注解

@Conditional

条件装配: 满足Conditional指定的条件,则进行组件注入

Conditional还是个根注解,它下面还派生了非常多的注解,注解的功能可以来看一下Conditional

IDEA中找到@Conditional注解:

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

}

Ctrl + h打开继承数:

在这里插入图片描述

每一个注解代表了不同的功能,我们找几个具有典型代表的

@ConditionalOnBean

就是说当容器中存在我们指定的这个Bean(组件)的时候我们才干某些事情

相反的就有一个@ConditionalOnMissingBean:当容器中没有这个Bean(组件)的时候,我们才干某些事情

@ConditionalOnClass

当容器中有某ry一个类的时候,我们才干某些事情

相反的就有一个@ConditionalMissingClass:当容器中没有这个类的时候,我们才干某些事情(比如没有的时候给容器中注入哪些组件)

@ConditionalOnResource

当我们这个项目的类路径里面存在某一个资源的时候,我们才干什么

@ConditionalOnJava

是指定某些java版本号后我们才干什么

@ConditionalOnWebApplication

当我们这个应用是web应用的时候,我们才干什么

相反的就有一个@ConditionalOnNotWebApplication当我们的应用不是web应用的时候我们做什么

@ConditionalOnSingleCandidate

当我们容器中指定了这个组件只有一个实例或者它有多个实例但是有一个东西是我们的说的主实例(也就是我们用@Primary我们标注的)说明@ConditionalOnSingleCandidate才生效

@ConditionalOnProperty

当配置文件里面配置了某个属性的时候我们才干某些事情

等等

取出这些例子,来做俩个实例

@ConditionalOnBean

还是来到MyConfig.java配置类:

package com.chentianyu.boot.config;

import com.chentianyu.boot.bean.Pet;
import com.chentianyu.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @Configuration 标注在一个类上告诉它(Spring)这是一个配置类
 * 1、配置类里面我们可以使用@Bean标注在方法上给容器注册组件,默认也是单实例的
 * 2、需要注意的是@Configuration标注的这个类,它本身也是一个组件
 * 3、proxyBeanMethods: 代理Bean的方法
 */
//@Component
@Configuration(proxyBeanMethods = false)//告诉SpringBoot这是一个配置类(把这个类说明@Configuration类似于告诉spring这个文件是配置文件)
public class MyConfig {
    /**
     * 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象
     * @return
     */
    @Bean //我们不用<Bean>标签,我们用@Bean注解
    public User user01(){
        return new User(18, "lisi");
    }

    @Bean("tom")
    public Pet tomcatPet(){
        return new Pet("tomcat01");
    }
}

这段配置我们看到user01()我们给容器中注册(@Bean)了一个user01组件,这个组件有没有,它不一定。假设我们给容器中都没有注册(//@Bean("tom"))这个tom组件。为了不引起报错,把主程序写的全都注释掉;我们调用一下conrainsBean()方法,我们判断一下我们容器中是不是包含我们某个组件。

//@Bean("tom")
public Pet tomcatPet(){
	return new Pet("tomcat01");
}

现在它就是一个常规方法。它并不能给容器中注册组件,看一下容器中是不是有tom组件。

主程序中测试:

boolean tom = run.containsBean("tom");
System.out.println("容器中是否有tom组件:" + tom);

得到结果:

容器中是否有tom组件:false

那有没有user01呢?(user01方法上有@Bean注解)

boolean user01 = run.containsBean("user01");
System.out.println("容器中是否有user01组件:" + user01);

得到结果:

容器中是否有user01组件:true

但是我最终想要的效果是:我们这个user01用户依赖这个宠物tomcatPet,如果容器中没有这个宠物,你也别给我从容器中注册这个用户了。所以我们可以用到条件注解@ConditionalOnBean,OnBean就是说在容器中有某个组件,有哪个组件呢?我们可以在()指定

ConditionalOnBean.java

package org.springframework.boot.autoconfigure.condition;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.Conditional;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {

	Class<?>[] value() default {};

	String[] type() default {};

	Class<? extends Annotation>[] annotation() default {};

	String[] name() default {};

	SearchStrategy search() default SearchStrategy.ALL;

	Class<?>[] parameterizedContainer() default {};

}

在这个Bean里面呢,我们可以使用Class<?>[] value() default {};指定我们这个组件的类型,当容器里面有这个组件的时候;

String[] name() default {};:还有我们组件的名字

@ConditionalOnBean(name = "name")

当我们这个容器中有这个名字的组件,哪个名字呢?

@ConditionalOnBean(name = "tom")

有tom组件的时候 , 我呢在给容器中注入user01组件

结果为:

容器中是否有tom组件:false
容器中是否有user01组件:false

@ConditionalOnBean(name = "tom")甚至可以标注在类上,标注在类上也就是说当容器中有tom组件的时候,下面方法才生效,否则下面方法都不生效

@ConditionalOnMissingBean

@ConditionalOnMissingBean(name = "tom")
public class MyConfig {

 /**
     * 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册容器中的单实例对象
     * @return
     */
    @Bean //我们不用<Bean>标签,我们用@Bean注解
    public User user01(){
        User lisi = new User(18,"lisi");
        lisi.setPet(tomcatPet());
        return lisi;
    }

    //@Bean("tom")
    @Bean("tom22")
    public Pet tomcatPet(){
        return new Pet("tomcat01");
    }
}

则结果为:

容器中是否有tom组件:false
容器中是否有user01组件:true
容器中是否有tom22组件:true

当我们没有tom(@ConditionalOnMissingBean(name = "tom"))user01tom22就有了


所以我们这些条件注解如果加在方法上,当我们这个条件成立以后,我们这个方法返回的组件才会被注册在容器中,否则就不注册;如果加在类上,当我们这个条件成立以后,我们类下面的配置才能生效,否则呢就不生效。这是我们说的条件装配。大家未来在springboot底层里面会遇到非常多的条件装配。这是以ConditionalOnBean为例。

在SpringBoot底层经常会有这些判断:比如我们导入了某些场景,当我们这些场景里面什么东西配了以后我才帮你配什么(比如ConditionalOnBean),什么东西没配我就不帮你配了;或者是你缺少什么了(比如@ConditionalOnMissingBean),我帮你配什么

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

结城明日奈是我老婆

支持一下一直热爱程序的菜鸟吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值