@Conditional相关注解

一、@Conditional

@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册Bean。

代码例子:

package com.cy.conditional;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:20
 */
public interface ListService {
    public String showListCmd();
}
View Code
package com.cy.conditional;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:21
 */
public class LinuxListService implements ListService{
    @Override
    public String showListCmd() {
        return "ls";
    }
}
View Code
package com.cy.conditional;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:21
 */
public class WindowsListService implements ListService{
    @Override
    public String showListCmd() {
        return "dir";
    }
}
View Code

WindowsCondition:

package com.cy.conditional;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:20
 */
public class WindowsCondition implements Condition {

    @Override
    public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
        return arg0.getEnvironment().getProperty("os.name").contains("Windows");
    }

}

LinuxCondition:

package com.cy.conditional;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:19
 */
public class LinuxCondition implements Condition {

    @Override
    public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
        return arg0.getEnvironment().getProperty("os.name").contains("Linux");
    }

}

配置类Config:

package com.cy.conditional;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:21
 */
@Configuration
public class ConditionConfig {

    @Bean
    @Conditional(WindowsCondition.class)
    public ListService windowsListService() {
        return new WindowsListService();
    }

    @Bean
    @Conditional(LinuxCondition.class)
    public ListService linuxListService() {
        return new LinuxListService();
    }

}

测试类:

package com.cy.conditional;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:22
 */
public class App {
    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(
                ConditionConfig.class);

        ListService ls = context.getBean(ListService.class);
        System.out.println(context.getEnvironment().getProperty("os.name")
                + "系统下的列表命令为:" + ls.showListCmd());
    }
}

console:

Windows 10系统下的列表命令为:dir

 

 

二、@ConditionalOnClass

例如:@ConditionalOnClass(KafkaTemplate.class)

表示:Spring工程中引用了Kafka的包 才会构建这个bean。就是说只有在classpath下能找到kafkaTemplate类才会构建这个bean。

 

三、@ConditionalOnBean

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)

参考博客:https://www.cnblogs.com/qdhxhz/p/11027546.html

代码例子:

1.实体类:

package com.cy.model;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * @description com.cy.model
 * @author: chengyu
 * @date: 2022-04-22 11:40
 */
@Setter
@Getter
@ToString
public class Mother {
    String name;
    int age;
    Son son;
}
View Code
package com.cy.model;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * @description com.cy.model
 * @author: chengyu
 * @date: 2022-04-22 11:40
 */
@Setter
@Getter
@ToString
public class Son {
    String name;
    int age;
}
View Code

2.配置类:

package com.cy.conditional;

import com.cy.model.Mother;
import com.cy.model.Son;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class ConditionConfig {


    /*@Bean
    public Son son(){
        Son s = new Son();
        s.setAge(10);
        s.setName("小明");
        return s;
    }*/

    @Bean
    @ConditionalOnBean(Son.class)
    public Mother mother(Son son){
        Mother m = new Mother();
        m.setAge(40);
        m.setName("小慧妈妈");
        m.setSon(son);
        return m;
    }
}

3.测试类:

package com.cy.conditional;

import com.cy.model.Mother;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @description com.cy.conditional
 * @author: chengyu
 * @date: 2022-04-22 11:37
 */
@Controller
@Slf4j
public class ConditionController {

    @Autowired(required = false)
    private Mother mother;

    @ResponseBody
    @RequestMapping("/testConditionOnBean")
    public void conditionOnBean() {
        System.out.println(mother);
    }
}

4.测试结果:

a.当不存在Son实体类被注入时,如果private Mother mother上面直接是@Autowired时,启动就会报错:

Field mother in com.cy.conditional.ConditionController required a bean of type 'com.cy.model.Mother' that could not be found.

因此需要在@Autowired后面写上(required=false),required=false 的意思就是允许当前的Bean对象为null。正常启动后打印:null

b.当打开Son @Bean的注释后,重新启动,控制台打印:

Mother(name=小慧妈妈, age=40, son=Son(name=小明, age=10))

 

 

 

四、其他的

@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)

@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)

@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)

@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)

@ConditionalOnNotWebApplication(不是web应用)

 

五、@ConditionalOnProperty

@ConditionalOnProperty(prefix="person" name = "super.enable", matchIfMissing = false, havingValue = "true")  代表什么意思呢?

也是控制配置类是否生效;配置为:person.super.enable

prefix: 配置文件的前缀

name: 配置的名字,name或value是必填项。

havingValue: 与配置的值对比值,当两个值相同返回true,配置类生效。

matchIfMissing: 当未找到对应配置是否匹配,默认不匹配。该属性为true时,配置文件中缺少对应的value或name的对应的属性值,也会注入成功。

例如:@ConditionalOnProperty(prefix = "aspectLog", name = "enable",havingValue = "true", matchIfMissing = true)当配置文件有aspectLog.enable=true时开启,如果配置文件没有设置aspectLog.enable也开启。

 

 

 

 

---

 

posted on 2022-04-22 11:10  有点懒惰的大青年  阅读(106)  评论(0编辑  收藏  举报