一、基本认识
Spring 的配置文件名字一般叫做 applicationContext.xml
- 存放位置:放在 Maven 项目中的 main —> resources
- 创建方式:resources —> new —> XML Configuration File —> Spring Config
二、Bean 标签
1. Bean 基本配置
用于配置对象交由 Spring 通过反射的方式来创建。
默认情况下 Spring 通过反射的方式,调用的是类中的无参构造函数,如果没有无参构造则无法成功创建。
基本属性:
测试 singleton 单例
1. Bean 对象的数量
可以看到 Spring 容器的 Bean 对象的数量只有一个
2. Bean 对象的创建时机
我们知道在 singleton 范围下,Spring 会使用无参构造创建 Bean 对象,那什么时候创建的呢?
为了测试在 singleton 范围下对象的创建时机,我们在 Bean 类中重写一个无参构造
然后在 Spring 加载配置文件生成 Spring 容器的那一行代码打上断点
执行断点测试
一开始如下:配置文件还没有被加载
执行单步操作
后结果如下:
重点:可以看到,当执行了第13行的代码,也就是加载配置文件,创建 Spring 容器的时候呢,singleton 范围的单例对象就已经调用无参构造被创建了出来,这里还没有调用 app.getBean( ) 方法!
当我们继续执行两次 getBean( ) 的时候也可以看到,不会再调用任何构造方法了!它只被调用一次!
测试 propotype 多例
1. Bean 对象的数量
可以看到 Spring 容器的 Bean 对象的数量不止有一个
2. Bean 对象的创建时机
- 在上面我们已经知道,在 scope 设置为 singleton 范围的时候,Bean 对象在加载配置文件并生产 Spring 容器的时候就会同时调用无参构造创建一个 Bean 对象,并且后面无论调用几次 getBean( ) 方法也不会在调用构造方法来创建 Bean 对象,之后 getBean 拿到的 Bean 对象都是之前创建的单例对象。
- 而在 scope 设置为 propotype 范围的时候,Bean 对象不会在加载配置文件并生产 Spring 容器的时候调用构造函数来创建 Bean 对象,而是在 getBean( ) 方法被调用的时候才调用构造函数来生成对象!
可以看到,加载配置文件,生成 Spring 容器的时候并没有调用构造函数生成 Bean 对象
而后,调用了两次 getBean( ) 方法就会分别调用两次构造函数创建两个不同的 Bean 对象!

3. Bean 生命周期配置
- init-method : 指定类中的初始化方法的名称, 即构造方法使用之后调用的方法
- destroy-method : 指定类中销毁方法的名称
- 在 Spring 的配置文件的 Bean 标签里使用上述两个属性的时候都必须先在 Bean 类中创建出初始化方法和销毁方法!



可以看到, 初始化方法被执行了,但是销毁方法并没有执行, 为啥呢,因为还来不及执行, Ioc 容器就被销毁了, 这里我们手动将 Ioc 容器给关闭一下就可以了:
但你发现, ApplicationContext 这个接口中并没有 close( ) 方法, 只有 ClassPathXmlApplicationContext 这个实现类才有 close( ) 方法, 所以我们可以将
ApplicationContext 改为 ClassPathXmlApplicationContext :
这样就不会报错了
销毁方法也被执行了。
4. Bean 实例化的三种方式
Spring 的 Ioc 容器默认是用无参构造来创建 Bean 对象, 我们也可以指定不用默认的无参构造来创建,但还是第一种最重要。
- 无参构造方法实例化
- 工厂静态方法实例化
-
1. 无参构造方法实例化
就是将 scope 设置为 singleton ,不设置也行,默认就是 singleton 的,然后在测试类中通过 Spring 的 Ioc 容器调用 getBean( ) 方法即可。
2. 工厂静态方法实例化
既然是工厂静态方法,那肯定得先要有工厂类,还有工厂的静态方法。

下一步就是在配置文化中进行配置,告诉 Spring Ioc 容器不要用无参构造方法来给我造对象,而是使用工厂的静态方法来实例化对象:
可以这样来获取该工厂类的全限定名
然后将 Bean 标签的 class 属性改成工厂类的全限定名,但是只加 class 属性的话还不够,Spring 容器还是会调用该工厂类的无参构造方法来实例化对象,这时候咋办呢?简单,加一个 factory-method 属性,该属性的值就是实例化对象要使用的静态方法的名称即可,这样做的话,Spring 容器在实例化对象的时候,就会去找该工厂类的静态方法去实例化对象。
Tip:我们做了上面这么多的操作,改变了 Bean 标签的 class 属性,但是原来测试类中用 Spring 容器获取对象的代码一行也不用改变,这也就体现了我们所说的解耦!
3. 工厂实例方法实例化

要注意,第2点我们使用工厂的静态方法来实例化对象,调用静态方法不需要工厂对象,也就是不需要 Spring 容器帮我们创建工厂对象,但是现在我们要用工厂的实例方法来创建对象,这就意味着我们需要先让 Spring 容器帮我们创建一个工厂对象,在利用这个工厂对象调用实例化方法来创建出我们想要的对象:

测试类获取 UserDao 对象的代码仍旧不需要改变!哇哦!解耦!
4. Bean 的依赖注入分析
根据我之前没有使用框架开发的网站的经历来看:我需要在 Service 业务层获取到 Dao 持久层的对象,然后再在业务层通过持久层的对象去调用持久层的方法从而实现业务层的方法逻辑。
这里就出现问题了,我们在业务层需要创建一个业务层对象来调用持久层的对象,那显而易见的,我们也需要在持久层创建一个对象供业务层调用,换句话说,就是业务层的对象需要调用持久层的对象,而我们现在学到的就只能让 Spring 容器去同时容纳这两个对象,然后再在代码中获取到业务层的对象和持久层的对象,然后再在业务层中去调用持久层的对象,这里,Spring 容器创建了两个对象,而这两个对象在 Spring 容器外部产生了依赖关系!
那如何解决呢,就是要在 Spring 容器里面将这种依赖关系直接给维护了!我们在容器外部只需要调用业务层的对象就行了!
5. Bean 的依赖注入概念
依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了 Spring ,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。
那这种业务层和持久层的依赖关系,在使用 Spring 之后呢,就可以让 Spring 来维护了。
就是 Service层 依赖 Dao层 的注入!
简单的说,就是坐等 Spring 框架把持久层对象传入业务层,而不用我们自己去获取。
6. Bean 的依赖注入方式
怎样将 UserDao 注入到 UserService 内部呢?
set 方法(常用)
-
6.1 set 方法实现依赖注入
要用 set 方法实现依赖注入,那肯定就得先在 UserServiceImpl 实现类中增加一个 UserDao 成员变量,然后再创建一个 set 方法:

接下来我们要在配置文件中,告诉 Spting 容器:你要在容器里面将 UserDao 注入给 UserService!
ref 就是容器当中的 userDao 对象!
- name 就是表示 userService 对象的 setUserDao( ) 方法!通过引用 ref 来注入一个对象类型!**注意这里的属性 name 是 set 方法后面的一串英文字母,然后第一个字母变为小写即可,我测试了一下,就是这样的!**
- 这样就可以把容器当中的 userDao 对象注入给到 userService 对象的 set 方法!

成功执行,完成注入!
特别的,当我们用 new 的方式来创建 UserService 对象,而不是在容器里面拿 UserServie 对象,就会产生空指针异常,因为自己 new 的 Userservice 对象并没有容器帮我们注入 UserDao!
又有个特别的 set 方法注入也可以写成 p 命名空间注入,更简单
- 首先需要引入 p 命名空间:

- 然后进行下面的操作也可以实现注入对象:

- **P 命名空间注入本质也是 set 方法注入。
6.2 有参构造方法实现依赖注入


这里的 name 指的是有参构造的参数名,ref 仍然指的是容器中的 userDao 对象。
成功注入!
7. Bean 的依赖注入的数据类型
注入的前提都是要有 set 方法!
注入时的 propety 标签的 name 属性值都指的是 set 方法的方法名字中把 set 三个字母去掉之后首字母变为小写**的一串英文字母。**
除了对象可以注入,普通的数据类型,集合的数据类型也都可以使用容器来注入!
- 引用数据类型
- 普通数据类型
- 集合数据类型
7.1 引用数据类型
就是我们上面注入的对象。
使用 ref 来注入。
7.2 普通数据类型
使用 value 来注入,普通数据类型的值不像引用数据类型,不用在 IOC 容器里面存在,我们可以直接用字符串呀、整型呀啥啥啥的直接给值就行。
7.3 集合数据类型
在标签体中用
测试:
首先用注入的方式在 Ioc 容器中创建两个 User 对象 user1 和 user2 供 Map 集合使用:

接下来就往集合中注入数据:
成功注入:
三、import 标签
引入其他配置文件(分模块开发)
实际开发中,Spring 的配置内容非常多,这就导致 Spring 配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在 Spring 主配置文件中通过 import 标签进行加载即可。
四、总结


