本篇文章,讨论两个事情,即如何控制 Bean 的装配以及 Bean 的作用范围。
条件装配
让 IoC
容器有条件的装配 Bean
,是 @Conditional 可以做的事情。有些时候某些客观因素会使一些 Bean 无法进行初始化,比如数据库连接失败,这种情况下,我们可能并不希望 IoC 容器去装配数据源的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Configuration @ComponentScan(basePackages = "com.yuegs") public class PersonConfig {
@Autowired Person person ;
@Bean @Conditional(PersonConditional.class) Person getPerson(){ return person ; } }
class PersonConditional implements Condition {
@Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { String person_switch = context.getEnvironment().getProperty("person_switch"); return "true".equals(person_switch); } }
|
Bean 作用域
通过 IoC 容器最顶级接口 BeanFactory,可以看到,其中以后两个方法:isSingleton
和 isPrototype
。
isSingleton
如果返回为 true,则 Bean 在 IoC 容器中以单例存在,这也是 Spring IoC 容器的默认值。
isPrototype
如果返回为 true,则我们每次获取 Bean 时,IoC 容器都会为我们创建一个新的 Bean。
以上,其实就是 Spring Bean 的两种作用域问题。
1 2 3 4 5 6 7 8
| public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; ... boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException; ... }
|
1 2 3 4 5 6 7 8
| @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class Banana implements Fruit{ @Override public String getFruitName() { return "Banana"; } }
|
测试:
1 2 3 4 5 6 7 8 9 10 11
| @Component public class Person { @Autowired private Banana banana1 ; @Autowired private Banana banana2 ;
public boolean compareBanana(){ return banana1 == banana2 ; } }
|
1 2 3 4 5 6 7 8
| public static void beanScopeTest(){ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig.class) ; Person p1 = context.getBean(Person.class) ; System.out.println("banana is the same:"+p1.compareBanana()); Person p2 = context.getBean(Person.class) ; System.out.println("people is the same:"+(p1 == p2)); context.close(); }
|
结果:
1 2
| banana is the same:false people is the same:true
|