条件化的Bean
例
@Bean
@Conditional(MagicExistsCondition.class) //这个注解 只有在给定的条件计算为true时才会创建Bean
public MagicBean magicBean()
{
return new MagicBean();
}
设置给@Conditional的类可以是任意实现了Condition接口的类
public interface Condition
{
boolean matches (ConditionContext ctxt, AnnotatedTypeMetadata metadata);
}
实现这个接口只需提供matches方法的实现即可
例
public class MagicExistsCondition implements Condition
{
public boolean matches(
ConditionContext context ,AnnotatedTypeMetadata metadata)
{
Environment env = context.getEnvironment();
return env.containsProperty("magic");
}
}
处理自动装配的歧义性
例
@Autowired
public void setDessert(Dessert dessert)
{
this.dessert = dessert;
}
这个例子中Dessert是一个接口 有三个类实现了这个接口发 分别是
@Component
public class Cake implements Desserent{}
@Component
public class Cookies implements Desserents{}
@Component
public class IceCream implements Desserents{}
这三个实现均使用了@Component注解,Spring会扫描他们并创建为Spring应用上下文中的Bean
但是Spring无法做出选择 并抛出异常
在声明Bean时可以将其中一个可选的Bean设置为首选项
例
@Component
@Primary
public class IceCream implements Dessert{}
如果标记了多个同一类型的Bean 例如多个Dessert bean Spring就无法从这些首选项中做出选择
Spring的限定符能够在所有可选的Bean上进行缩小范围的操作,最终能达到只有一个Bean满足所规定的限定条件
例
@Autowired
@Qualifier("iceCream") //这个注解限定了注入的Bean为iceCream
public void setDessert(Dessert dessert)
{
this.dessert = dessert;
}
如果将IceCream类重构了,将其重命名,这时就会出现无法匹配的情况
这时就需要自定义的限定符
例
@Component
@Qualifier("cold")
public class IceCream implements Dessert{}
@Autowired
@Qualifier("cold")
public void setDessert(Dessert dessert)
{
this.dessert = dessert;
}
自定义的限定符注解
在上面的例子中如果引入了新的Dessert bean
@Component
@Qualifier("cold")
public class Popsicle implements Dessert{}
现在Spring 在自动装配时再次遇到了歧义性问题需要更多的限定符将可选范围限定在一个Bean
@Component
@Qualifier("cold")
@Qualifier("creamy")
public class IceCream implements Dessert()
在注入点中也可以用这样的方式将范围缩小到IceCream
@Autowired
@Qualifier("cold")
@Qualifier("creamy")
public void setDessert(Dessert dessert)
{
this.dessert = dessert;
}
这里有一点问题,java不允许在同一个条目上重复出现相同的多个注解,如果试图这样做,编译器会提示错误
这时候,可以创建自定义的限定符注解
例
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,
ElementType.METHOD,ElenentyType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold{}
同样也可以创建一个一个新的@Creamy注解
现在我们重新看一下IceCream ,为其添加@Cold和@Creamy注解
@Component
@Cold
@Creamy
public class IceCream implements Dessert{}
最后,在注入点使用必要的限定符注解,从而将可选取范围缩小到只有一个Bean满足需求
@Autowired
@Cold
@Creamy
public void setDessert (Dessert dessert)
{
this.dessert = dessert;
}