美文网首页
深入浅出@Conditional注解使用方法

深入浅出@Conditional注解使用方法

作者: 山间草夫 | 来源:发表于2020-09-01 07:43 被阅读0次

写作目的

了解spring 中ConditionXXX相关注解的使用方法.

​ 目录大纲:

(1)例子说明

(2)编码思路

(3)编写条件类WindowCondition和LinuxCondition

(4)编写接口CmdService以及两个实现类

(5)编写配置类,根据条件进行注入不同的类

(6)编写测试代码

(7)Spring提供的Condition

(8)题外话:怎么在Condition中获取application.properties的配置项

接下里看下具体的内容:

1. 例子说明

在java中这种情况,调用系统的cmd命令,但是我们知道在window和linux下命令有些有些时候是不一样的,那么我们以前一般是这么处理;

Java代码

伪代码:

 if(window){ 
         //具体的处理代码 
 }else if(Linux){ 
         //具体的处理代码. 
 } 

当具体的处理代码很多的时候,我们会放到另外一个处理类来进行处理,比如:WindowService和LinuxService。你有没有发现这里如果我们使用了@Service进行注解WindowServie和LinuxService的话,那么内存中就会存在两个Service,而实际上有一个service根本一次都不会执行到。好了,针对于这个问题@Conditional就可以解决。当然它还有其它强大的地方。

2. 编码思路

(a)首先这里的话,有一个条件表达式的编写,满足什么条件下返回true,这个是接口Condition,我们需要去实现它;

(b)当满足条件的时候,进行做什么事情,这里使用的是@Conditional,当@Conditional(条件类.class)中的条件类返回true的时候,@Conditional所注解的类或者方法就会执行。

3. 编写条件类WindowCondition和LinuxCondition

WindowCondition

Java代码

package com.kfit.demo.condition;  

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

/** 
 * window操作系统的条件:当在Window系统下运行的时候,matches方法会返回true,否则返回false. 
 * @author Angel --守护天使 
 * @version v.0.1 
 * @date 2017年8月23日 
 */  
public class WindowCondition implements Condition{  

    /** 
     * 这里写自己的逻辑,只有返回true,才会启用配置 
     */   
    @Override  
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {  
       return context.getEnvironment().getProperty("os.name").contains("Windows");  
    }  
}  

window操作系统的条件: 当在Window系统下运行的时候,matches方法会返回true,否则返回false.

LinuxCondition:

Java代码

package com.kfit.demo.condition;  

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

/** 
 * Linux操作系统的条件:当在Linux系统下运行的时候,matches方法会返回true,否则返回false. 
 * @author Angel --守护天使 
 * @version v.0.1 
 * @date 2017年8月23日 
 */  
public class LinuxCondition implements Condition{  

    /** 
     * 这里写自己的逻辑,只有返回true,才会启用配置 
     */   
    @Override  
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {  
       return context.getEnvironment().getProperty("os.name").contains("Linux");  
    }  

}  

Linux操作系统的条件: 当在Linux系统下运行的时候,matches方法会返回true,否则返回false.

4. 编写接口CmdService以及两个实现类

CmdService

Java代码

package com.kfit.demo;  

public interface CmdService {  
    public void print();  
}  

接口类,具体实现代码有两个service,WindowCmdService和LinuxCmdService。

WindowCmdService:

Java代码

package com.kfit.demo.service;  

import com.kfit.demo.CmdService;  

public class WindowCmdService implements CmdService{  

    @Override  
    public void print() {  
       System.out.println("Window cmd...");  
    }  

} 

LinuxCmdService:

Java代码

package com.kfit.demo.service;  

import com.kfit.demo.CmdService;  

public class LinuxCmdService implements CmdService{  

    @Override  
    public void print() {  
       System.out.println("Linux cmd...");  
    }  

}  

注意:以上的两个实现类WindowCmdService和LinuxCmdService这里我们并没有使用@Service注解进行注入,下面我们使用配置类根据不同的系统注入不同的类。

5. 编写配置类,根据条件进行注入不同的类

CmdServiceConditionConfig:

Java代码

package com.kfit.demo.config;  

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

import com.kfit.demo.CmdService;  
import com.kfit.demo.condition.LinuxCondition;  
import com.kfit.demo.condition.WindowCondition;  
import com.kfit.demo.service.LinuxCmdService;  
import com.kfit.demo.service.WindowCmdService;  

/** 
 * 条件配置类. 
 * @author Angel --守护天使 
 * @version v.0.1 
 * @date 2017年8月23日 
 */  
@Configuration  
public class CmdServiceConditionConfig {  

    /** 
     * 当WindowCondition方法中的matches返回true的时候, 
     * WindowCmdService会被注入,否则不注入。 
     */  
    @Bean("cmdService")  
    @Conditional(WindowCondition.class)  
    public CmdService windowCmdService(){  
       return new WindowCmdService();  
    }  


    /** 
     * 当LinuxCondition方法中的matches返回true的时候, 
     * LinuxCmdService会被注入,否则不注入。 
     */  
    @Bean("cmdService")  
    @Conditional(LinuxCondition.class)  
    public CmdService LinuxCmdService(){  
       return new LinuxCmdService();  
    }  
}

这里使用@Conditional根据满足不同的条件注入不同的类,在Linux下会注入实现类LinuxCmdService,在Window下会注入WindowCmdService。

6. 编写测试代码

在启动类的main方法中编写测试代码:

Java代码

public static void main(String[] args) {  
       ApplicationContext ctx =  (ApplicationContext) SpringApplication.run(App.class, args);  
       CmdService cmdService = ctx.getBean(CmdService.class);  
       cmdService.print();  
    }  

在Window下运行控制台打印信息:

Window cmd...

在Linux下运行控制台打印信息(亲测):

Linux cmd...

7. Spring提供的Condition

除了自己自定义Condition之外,Spring还提供了很多Condition给我们用

(a)@ConditionalOnBean

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

(b)@ConditionalOnClass

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

(c)@ConditionalOnExpression

当表达式为true的时候,才会实例化一个Bean。

比如:

@ConditionalOnExpression("true")

@ConditionalOnExpression("${my.controller.enabled:false}")

(d)@ConditionalOnMissingBean

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

(e)@ConditionalOnMissingClass

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

(f)@ConditionalOnNotWebApplication

不是web应用

8. 题外话:怎么在Condition中获取application.properties的配置项

在实际开发中,我们的条件可能保存在application.properties中,那么怎么在Condition中获取呢,这个很简单,主要通过ConditionContext进行获取,具体代码如下:

Java代码

String port = context.getEnvironment().getProperty("server.port");  
System.out.println(port); 

相关文章

网友评论

      本文标题:深入浅出@Conditional注解使用方法

      本文链接:https://www.haomeiwen.com/subject/nnqpsktx.html