概述
假设在某些特定的场景下,希望根据特定的条件去加载某个或某些bean,我们可以使用@Condtional注解, Spring 4.0的时候加入的这个注解。
例子
假设,我们在配置了数据库的几个属性时,才去实例化bean,否则不初始化这个bean。这个例子可能不太合适,权当理解这个注解的用法了
Step1 实现Condition接口,重写matches方法
package com.artisan.springbootmaster.conditional; 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 DatabaseCondtional implements Condition { /** * 数据库bean的装配条件 * * @param context 上下文 * @param metadata 注释类型的元数据 * @return true 装配Bean ,否则不装配 */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 根据context取出对应的Env信息 Environment environment = context.getEnvironment(); // 判断属性文件是否存在对应的数据库配置 return environment.containsProperty("datasource.driverName") && environment.containsProperty("datasource.url") && environment.containsProperty("datasource.username") && environment.containsProperty("datasource.password"); } }
Step2 在对应的@Bean上使用@Conditional注解
package com.artisan.springbootmaster.conditional; import org.apache.commons.dbcp2.BasicDataSourceFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.*; import javax.sql.DataSource; import java.util.Properties; @Configuration @PropertySource(value = "classpath:jdbc.properties",ignoreResourceNotFound = true) public class Config { @Bean(name = "datasource" ,destroyMethod = "close") @Conditional(DatabaseCondtional.class) public DataSource initDataSource( @Value("${datasource.driverName}") String driver, @Value("${datasource.url}") String url, @Value("${datasource.username}") String username, @Value("${datasource.password}") String password){ System.out.println("driver:" + driver + "\n url:" + url+ "\n username:" + username + "\n password:" + password) ; Properties properties = new Properties(); properties.setProperty("driver",driver); properties.setProperty("url",url); properties.setProperty("username",username); properties.setProperty("password",password); DataSource dataSource = null; try { dataSource = BasicDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } return dataSource; } }
测试
package com.artisan.springbootmaster.conditional; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import javax.sql.DataSource; public class Test { public static void main(String[] args){ ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class); //DataSource dataSource = (DataSource) ctx.getBean("datasource"); DataSource dataSource = ctx.getBean(DataSource.class); System.out.println("datasource:" + dataSource); } }
结果
当我们修改掉某个属性后,DatabaseCondtional#matches方法肯定返回false, 按照推测,该bean不会被加载到IoC容器中,我们来验证下
将 datasource.driverName 改为 datasource.driverName1
重新测试,抛出了异常。
因为我们在获取bean的时候,IoC容器中并不存在该bean。
其他相关的注解