Conditional beans
通过条件判断是否要创建bean
配置
@Configuration
public class MagicConfig {
@Bean
@Conditional(MagicExistsCondition.class)
public MagicBean magicBean() {
return new MagicBean();
}
}
实现
- 任何实现了Condition 接口都可以用来当做Conditional的条件
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
- ConditionContext的接口
- BeanDefinitionRegistry getRegistry(): 获取beah的定义
- ConfigurableListableBeanFactory returned from getBeanFactory():查看当前bean,甚至可以查看bean properties信息
- ResourceLoader getResourceLoader():获取查看加载的resource
- ClassLoader getClassLoader(): 查看已经加载classes
public interface ConditionContext {
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
Environment getEnvironment();
ResourceLoader getResourceLoader();
ClassLoader getClassLoader();
}
- AnnotatedTypeMetadata
可以查看annotations信息,也可以查看@bean注释的方法信息。
public interface AnnotatedTypeMetadata {
boolean isAnnotated(String annotationType);
Map<String, Object> getAnnotationAttributes(String annotationType);
Map<String, Object> getAnnotationAttributes(
String annotationType, boolean classValuesAsString);
MultiValueMap<String, Object> getAllAnnotationAttributes(
String annotationType);
MultiValueMap<String, Object> getAllAnnotationAttributes(
String annotationType, boolean classValuesAsString);
}
解决bean 歧义问题
JavaConfig 指定Primary bean
@Bean
@Primary
public Dessert iceCream() {
return new IceCream();
}
xml 指定Primary bean
<bean id="iceCream"
class="com.desserteater.IceCream"
primary="true" />
@Qualifier("beanId")
- 每个bean都有一个默认的Qualifier,一般和beanId相同。使用默认的Qualifier当refactor代码时,会引入问题。最好使bean使用
@Qualifier("cold")
自定义qualifier. - 该注释可以与@Inject和@Autowired协同使用
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
自定义@Qualifier
问题:一般@Qualifier是根据共同的特征来命名,同样也会引入有歧义的bean,解决方式:
1.repeatable annotations
java 8中只要有@Repeatable
注释,该注释允许多次注释同一bean,即:
@Autowired
@Qualifier("cold")
@Qualifier("creamy")
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
2.自定义注释,原理同上
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold { }
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Creamy { }
@Component
@Cold
@Creamy
public class IceCream implements Dessert { ... }