1. 案例:通过ID从容器中获取Bean
1.1. 添加依赖

根据依赖传递,Spring核心容器只需要添加spring-context即可。在Spring5之前,核心容器还依赖commons-logging日志包,Spring5现在将commons-logging的内容集成到spring-jcl这个包下了。根据依赖传递,spring-jcl这个依赖也已经添加了,所以最后也只用添加spring-context这个依赖1
2
3
4
5
6<!-- Spring 核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
1.2. 编写Bean类
1 | package bean; |
1.3. 创建Spring Bean配置文件
在classpath下创建Bean配置文件。普通Java工程就放到src目录下,Maven工程就放到src/main/resources目录下
Eclipse如果安装了STS插件,可以直接New->Spring Bean Configuration File1
2
3
4
5
6
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
1.4. 在Bean配置文件中注册Bean
1 | <!-- |
1.5. 代码测试从容器中取出Bean
1 |
|
2. 案例:通过类对象从容器中获取Bean
除了ID,还可以通过类对象从容器中获取Bean。这种方式可以发现一个好处,即返回值不用类型转换1
2
3
4
5
6
7
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过类对象获取Bean
Person person = ioc.getBean(Person.class);
System.out.println(person);
}
3. 案例:同时指定ID和类对象,从容器中获取Bean
1 | <bean id="person1" class="bean.Person"> |
1 |
|
4. 案例总结
4.1. 谁创建了Bean?
我没有主动创建Person对象,是谁创建的呢?是Spring IOC容器
4.2. Bean是什么时候被创建的?是如何被创建的?
在IOC容器被创建时,即执行new ClassPathXmlApplicationContext时,所有在配置文件中注册过的Bean都会被创建
这里要注意,Spring有两种工厂。BeanFactory是在获取bean时才创建bean,而ApplicationContext容器在创建时就会创建所有配置的Bean
Bean又是如何被创建的呢?我们可以在Person中编写空参构造方法,输出一些内容1
2
3
4
5
6
7
8
public class Person {
public Person() {
System.out.println("Person被创建了");
}
private String name;
private Integer age;
}
再写一个测试方法。根据运行结果可知,IOC容器在创建时就创建了Bean,而且是通过反射,调用Bean的空参构造方法,创建一个实例1
2
3
4
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
}
4.3. 同一个Bean组件在IOC容器中是单实例的?
两次使用同一ID,从容器中取出Bean组件,得到的两个对象是相同的,说明Bean组件在IOC容器是单实例的1
2
3
4
5
6
7
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person1 = (Person) ioc.getBean("person");
Person person2 = (Person) ioc.getBean("person");
System.out.println(person1 == person2);
}
4.4. Bean的属性是如何被设置的?
在配置文件中,我们是通过property标签为Bean设置属性的。但这只是配置,我们并不知道IOC容器在程序中具体是如何为Bean设置属性的1
2
3
4<bean id="person" class="bean.Person">
<property name="age" value="10" />
<property name="name" value="foo" />
</bean>
给Person添加一个setter,输出一些内容1
2
3
4
5
6
7
8
9
public class Person {
private String name;
private Integer age;
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
}
运行测试方法,setter被调用了,可知IOC容器是通过反射,调用Bean的setter,将属性注入1
2
3
4
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
}
4.5. 如果容器中没有你要的组件,会出现什么现象?
先猜一下,如果没有你要的组件,可能会返回null
编写测试方法,取一个没有注册过的组件1
2
3
4
5
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Object bean = ioc.getBean("abc");
}
运行。结果并不是返回null,而是直接抛出异常1
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'abc' available
4.6. 如果定义了两个同类型的Bean组件,通过类对象获取Bean会出现什么现象
注册两个同类型的Bean,但是id不同1
2
3
4
5
6
7
8<bean id="person1" class="bean.Person">
<property name="age" value="10" />
<property name="name" value="foo" />
</bean>
<bean id="person2" class="bean.Person">
<property name="age" value="20" />
<property name="name" value="bar" />
</bean>
编写测试方法,通过类对象获取Bean1
2
3
4
5
6
7
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过类对象获取Bean
Person person = ioc.getBean(Person.class);
System.out.println(person);
}
运行,抛出异常。即通过类对象获取Bean时,要求容器中该类型的Bean组件只能有1个,如果有多个,就会报错。1
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'bean.Person' available: expected single matching bean but found 2: person1,person2
在这种情况下,只能通过ID获取1
2
3
4
5
6
7
8
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person1 = (Person) ioc.getBean("person1");
Person person2 = (Person) ioc.getBean("person2");
System.out.println(person1);
System.out.println(person2);
}