Bean 装载条件及作用域

本篇文章,讨论两个事情,即如何控制 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,可以看到,其中以后两个方法:isSingletonisPrototype
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

© 2024 YueGS