@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應用)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章