logo头像
Snippet 博客主题

Spring条件注解@Conditional

本文于540天之前发表,文中内容可能已经过时

@Conditional注解

Spring 4提供了一个基于条件的Bean的创建,即使用@Conditional注解.
@Conditional根据满足某一个特定条件创建一个特定的Bean.比如说,当某一个jar包在一个类路径下的时候,自动配置一个或多个Bean;或者只有某个Bean被创建才会创建另外一个Bean.
总的来说,就是根据特定条件来控制Bean的创建行为,这样我们可以利用这个特性来进行一些自动的配置.

Condition接口

设置给 @Conditional注解的类可以是任意实现了Condition接口的类型.可以看出,这些接口实现起来简单直接.只需要提供matches()方法的实现即可.
如果matches()方法返回true,那么就会创建带有@Conditional注解的bean.反之则不会创建Bean.
matches()方法有两个参数:ConditionContext类型和AnnotatedTypeMetadata类型:

  • ConditionContext接口能提供应用上下文信息:
    1. getRegistry()返回BeanDefinitionRegistry注册表,可以判断Bean的定义
    2. getBeanFactory()返回ConfigurableListableBeanFactory,可以检查Bean是否已经存在,甚至探查Bean的属性.
    3. getEnvironment()返回Environment,可以获取当前应用环境变量,也可以检测当前环境变量是否存在.
    4. getResourceLoader()返回ResourceLoader,用于读取或探查所加载的资源.
    5. getClassLoader()返回ClassLoader,用于检查类是否存在.
  • AnnotatedTypeMetadata接口能够让我们检查带有@Bean注解的方法上还有没有其他注解:
    1. isAnnotated()可以判断除@Bean注解外是否还有其他注解.
    2. getAllAnnotationAttributes()获取其他所有的注解属性
      下面我们来做一个以不同的操作系统来作为条件,通过实现Condition接口,并重写其matches方法来构造判断条件.若在Windows系统下运行程序,则输出列表命令为dir;若在Linux操作系统下运行程序,则输出列表命令为ls。

      代码演示

      1.导入POM依赖
      1
      2
      3
      4
      5
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.13.RELEASE</version>
      </dependency>

2.定义判断条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package cn.yeamin.spring.constant;

/**
* OS常量
* @author tong.li
*
*/
public final class Constants {

/**
* 私有构造,不让外部创建本类的实例对象
*/
private Constants() {}

public final static String OS_KEY = "os.name";
public final static String OS_TYPE_WINDOWS = "Windows";
public final static String OS_TYPE_LINUX = "Linux";


}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package cn.yeamin.spring.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import cn.yeamin.spring.constant.Constants;

/***
* 判断Linux的条件类
* @author tong.li
*/
public class LinuxCondition implements Condition {

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty(Constants.OS_KEY).contains(Constants.OS_TYPE_LINUX);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package cn.yeamin.spring.condition;

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

import cn.yeamin.spring.constant.Constants;

/***
* 判断Windows的条件类
* @author tong.li
*/
public class WindowsCondition implements Condition {

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty(Constants.OS_KEY).contains(Constants.OS_TYPE_WINDOWS);
}

}

3.业务实现:不同系统下不同的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package cn.yeamin.spring.service;

/**
* 命令服务接口
* @author tong.li
*/
public interface CommandService {

/**
* 抽象方法,显示操作系统的showList命令
* @return cmd
*/
String showListCommand();
}

1
2
3
4
5
6
7
8
9
10
11
package cn.yeamin.spring.service.impl;
import cn.yeamin.spring.service.CommandService;

public class LinuxCommandService implements CommandService {

@Override
public String showListCommand() {
return "ls";
}

}
1
2
3
4
5
6
7
8
9
10
11
12
package cn.yeamin.spring.service.impl;

import cn.yeamin.spring.service.CommandService;

public class WindowsCommandService implements CommandService {

@Override
public String showListCommand() {
return "dir";
}

}

4.定义配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package cn.yeamin.spring.conf;

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

import cn.yeamin.spring.condition.LinuxCondition;
import cn.yeamin.spring.condition.WindowsCondition;
import cn.yeamin.spring.service.CommandService;
import cn.yeamin.spring.service.impl.LinuxCommandService;
import cn.yeamin.spring.service.impl.WindowsCommandService;

/**
* 配置类
* @author tong.li
*
*/
@Configuration
public class ConditionConfig {

/**
* 声明一个Bean,并交给Spring容器去管理
* 通过@Conditional注解,操作系统为Windows则输出Windows下的dir命令
* @return
*/
@Bean
@Conditional(WindowsCondition.class)
public CommandService windowsCMD() {
return new WindowsCommandService();
}


/**
* 声明一个Bean,并交给Spring容器去管理
* 通过@Conditional注解,操作系统为Windows则输出Windows下的ls命令
* @return
*/
@Bean
@Conditional(LinuxCondition.class)
public CommandService linuxCMD() {
return new LinuxCommandService();
}

}

5.执行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package cn.yeamin.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import cn.yeamin.spring.conf.ConditionConfig;
import cn.yeamin.spring.constant.Constants;
import cn.yeamin.spring.service.CommandService;

/**
* 启动类
* @author tong.li
*
*/
@SuppressWarnings("all")
public class Bootstrap {

/**
* 执行测试基于不同操作系统显示不同的命令
* @param args
*/
public static void main(String[] args) {
// 加载配置类,创建基于注解式的应用上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionConfig.class);
//获取Bean
CommandService commandService = context.getBean(CommandService.class);
System.out.println(context.getEnvironment().getProperty(Constants.OS_KEY) + "系统下的显示列表命令为: " + commandService.showListCommand());
}
}

6.执行结果

1
Windows 7系统下的显示列表命令为: dir

1
linux系统下的显示列表命令为: ls
支付宝打赏 微信打赏

请作者喝杯咖啡吧