Spring @条件注释

时间:2020-01-09 10:44:33  来源:igfitidea点击:

使用Spring @Conditional注释,可以有条件地注册组件。使用@Conditional注释时,我们需要指定条件,并且仅在条件为true时才注册组件。

为了指定条件,我们需要实现org.springframework.context.annotation.Condition接口。

在哪里使用@Conditional注释

@Conditional注释可以通过以下方式之一使用:

  • 作为任何直接或者间接用@Component注释的类的类型级别注释,包括@Configuration类。如果@Configuration类标记有@Conditional,则与该类关联的所有@Bean方法,@ Import注释和@ComponentScan注释将受条件限制。
  • 作为元注释,用于组成自定义构造型注释。我们可以在Spring框架中使用@Conditional注释看到@Profile注释。
@Target(value={TYPE,METHOD})
@Retention(value=RUNTIME)
@Documented
@Conditional(value=org.springframework.context.annotation.ProfileCondition.class)
public @interface Profile
  • 作为任何@Bean方法的方法级注释

条件界面

org.springframework.context.annotation.Condition是具有单个抽象方法match()的功能接口。

matches(ConditionContext context, AnnotatedTypeMetadata metadata)

必须实现match()方法,并且用此方法检查的条件返回true或者false。如果返回true,则该组件已注册,否则未注册。

Spring @Conditional注释示例

有了有关@Conditional注释和Condition接口的基本知识,我们来看一个描述用法的示例。

我们需要做的是根据属性文件中的值注册" dev"数据源或者" prod"数据源。

src / main / resources / db.properties

#DB configuration for dev
db.dev.url=jdbc:oracle:thin:@localhost:1521/XEPDB1
db.dev.user=test
db.dev.password=test
db.dev.driver_class_name=oracle.jdbc.driver.OracleDriver

#DB configuration for prod
db.prod.url=jdbc:oracle:thin:@192.156.134.111:1523/XEPDB1
db.prod.user=sysuser
db.prod.password=test
db.prod.driver_class_name=oracle.jdbc.driver.OracleDriver

db.env=prod

配置类

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration("dbConfig")
@PropertySource(value="classpath:properties/db.properties")
public class DBConfiguration {
  @Autowired
  private Environment env;
  
  @Bean
  @Conditional(DevDBCondition.class)
  public BasicDataSource devDataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName(env.getProperty("db.dev.driver_class_name"));
    ds.setUrl(env.getProperty("db.dev.url"));
    ds.setUsername(env.getProperty("db.dev.user"));
    ds.setPassword(env.getProperty("db.dev.password"));
    return ds;
  }
	
  @Bean
  @Conditional(ProdDBCondition.class)
  public BasicDataSource prodDataSource() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName(env.getProperty("db.prod.driver_class_name"));
    ds.setUrl(env.getProperty("db.prod.url"));
    ds.setUsername(env.getProperty("db.prod.user"));
    ds.setPassword(env.getProperty("db.prod.password"));
    return ds;
  }
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {
  @Bean
  public UserDAO userDAO() {
    return new UserDAOImpl();
  }
}

条件类的实现

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

public class DevDBCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment env = context.getEnvironment();
    return env.getProperty("db.env").equals("dev");
  }
}
public class ProdDBCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    Environment env = context.getEnvironment();
    return env.getProperty("db.env").equals("prod");
  }
}

UserDAO界面

public interface UserDAO {
	public void getUsers();
}

UserDAOImpl类

public class UserDAOImpl implements UserDAO {
  @Autowired
  BasicDataSource ds;
  public void getUsers() {
    System.out.println("In getUsers method");
    System.out.println("Driver class name- " + ds.getDriverClassName());
    System.out.println("DB User- " + ds.getUsername());
    System.out.println("DB URL- " + ds.getUrl());
  }
}

运行该示例的类。

public class App {
  public static void main(String[] args) {
    AbstractApplicationContext context = new AnnotationConfigApplicationContext(DBConfiguration.class, UserConfig.class);
    UserDAO userDAO = context.getBean("userDAO", UserDAOImpl.class);
    userDAO.getUsers();
    context.close();
  }
}

输出:

In getUsers method
Driver class name- oracle.jdbc.driver.OracleDriver
DB User- sysuser
DB URL- jdbc:oracle:thin:@192.156.134.111:1523/XEPDB1

如我们所见,由于设置了db.env = prod,因此prodDataSource Bean已注册。如果我们更改db.env = dev并运行它,则在db.properties中,将注册devDataSource Bean。与该输出是

In getUsers method
Driver class name- oracle.jdbc.driver.OracleDriver
DB User- test
DB URL- jdbc:oracle:thin:@localhost:1521/XEPDB1