一、Spring 的概念
Spring : 包含众多工具方法的 IoC 容器。
Spring 的核心 :IoC (控制反转), DI (依赖注入)。
loC (Inversion of Control)翻译成中文就是 “控制反转” 的意思,控制反转一种编程设计思想,将程序的控制流程从传统的主动调用方式转变为被动接收方式(一个类的内部不再实例另一个类,而是告诉程序这个类需要那个类作为参数采用运行),从而实现对象和对象之间的解耦和依赖管理。
DI (Dependency Injection 的缩写——“依赖注入”)“依赖注入” 指的就是由 IoC 容器在运行期间(程序运行期间),动态地将某种依赖关系注入到对象之中。传统的做法是由程序主动去找他所依赖的对象然后进行实例化,而DI则是由容器主动地将依赖关系注入到对象中。这样做的好处是对象之间解耦。
既然 Spring 是一个 loC 容器,那么它就具备两个最基本的功能:
- 将对象存储到容器(Spring)中
- 从容器(Spring)中将对象取出来
在 Java 中一个普通的实例化的对象也被称之为 Bean 对象,在框架这一块我们遇到的对象就是以 Bean 对象称呼。
二、创建 Spring 项目
我们在了解 Spring 是啥之后,接下来结合 IDEA (集成开发环境) 演示如何创建一个 Spring 项目。
2.1 创建一个 普通的 Maven 项目(无需使用模板)
来到这个界面就说明创建成功了
2.2 添加 Spring 框架支持
Spring 是一个开源的 Java 框架,由 Rod Johnson 在 2002 年创建。Spring 提供了许多简化 Java 开发的功能,因此它在 Java 开发社区中得到了广泛的应用和认可。Spring 是第三方的资源(框架)是由大佬对已有的功能进行封装拓展,使得程序猿更容易地编写功能,并不属于 JDK 官方 , 所以我们要想使用 Spring 就需要下载第三方依赖。
只需要在项目中地 pom.xml 文档中添加 Spring 框架地支持, xml 配置如
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>
从上述配置中可以看出,添加的框架有 spring-context: spring 上下文, 还有 spring-beans : 管理对象的模块。具体有啥作用下文讲述。
1.3 添加一个启动类
最后在创建好的项目 Java 文件夹下创建一个启动类,包含 main 方法即可:
public class App {
public static void main(String[] args) {
}
}
在这个启动类中我们就可以对 Bean 对象进行一系列的操作。
三、将对象存储到 Spring
要想存储 Bean 对象(类实例化后的对象)需要有 2 步操作:
- 创建一个 bean 对象 —— 需要一个类
- 将 bean 对象 注册到 Spring 中 【使用 Spring 配置文件进行注册】
3.1 创建 Bean 对象
所谓 Bean 对象就是 Java 中的一个普通的对象。
public class Dog {
// 狗的属性
private String name;
private int age;
private String sex;
private String color;
// 狗的行为
public void cry() {
System.out.println(this.name + "汪汪~");
}
/**
* 小狗的做我介绍
* @return
*/
@Override
public String toString() {
return "Dog{" +
"我叫做:'" + name + '\'' +
", 我今年:" + age +
"岁, 我的性别是:" + sex +
", 我是'" + color + '\'' + "的" +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
常规的做法:
public class App {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("哈巴狗");
dog.setAge(3);
dog.setSex("公");
dog.setColor("白色");
dog.cry();
System.out.println(dog.toString());
}
}
3.2 将 Bean 对象注册到 Spring
这里介绍一种古老的注册方法——【使用 Spring 配置文件进行注册】
在创建好的项目中添加 Spring 的配置文件 spring-test.xml , 将该文件放到 resources 的根目录下:
这个配置文件 spring-test.xml 文件名可以任意的名称但是必须保证文件后缀为( .xml ),这里的文件名在后续的取 Bean 对象中会使用到。
该文件为 Spring 的配置文件,格式也是固定的(不需要记忆,找个文档保存一下即可):
<?xml version="1.0" encoding="UTF-8"?>
<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>
接下来,实现如何将 我们自定义的对象(Dog)注册到 Spring 中就可以了,具体的操作在 <beans> 标签中添加的。
<beans xmlns="http://www.springframework.org/schema/beans"
<bean id="dog" class="Dog"></bean>
</beans>
如果需要将多个 bean 对象注册到 Spring 中,重复以上操作即可。注意:需要给每个 bean 对象取别名(标识)。
四、从 Spring 获取并使用 Bean 对象
获取并使用 Bean 对象分为三个步骤:
- 获取 Spring 上下文对象(该对象维护了所有的 bean 对象),因为对象都交给了 Spring 管理,所以要从 Spring 中获取对象,就需要先得到 Spring 的上下文。
- 通过 Spring 的上下文,获取某一个指定(通过存储bean 对象的时候设置的标识)的 Bean 对象
- 返回值是 Bean 对象的实例,所以我们可以直接使用。
如果需要取出 多个 Bean 对象重复以上第 2,3 步骤即可
4.1 创建 Spring 上下文对象
Spring的上下文是指Spring容器中存储Bean对象的数据结构,也可以理解为Spring容器中的环境。
目前 Spring 上下文对象可以使用 ApplicationContext 接口来获取:
Spring框架中的ApplicationContext是一个IoC容器,负责管理应用程序中的Bean对象,它是一个配置文件,提供了Bean对象所需的配置信息,同时也是Bean对象的容器。通过ApplicationContext,开发人员可以将Bean对象存储在容器中,并在其他组件中使用这些Bean对象。
//1. 获取 Spring 上下文对象,创建的时候需要配置 Spring 的配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("spring-test.xml");
除了使用 ApplicationContext 之外,我们还可以使用 BeanFactory 接口来获取 Spring 的上下文。
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-test.xml"));
BeanFactory的主要作用是管理Bean的生命周期,包括Bean的创建、销毁和依赖注入等操作。BeanFactory是Spring框架中IoC容器的基础接口,它提供了对Bean对象的注册和获取。
不管是使用 ApplicationContext 还是使用 BeanFactory 获取 Spring 的上下文,二者的效果是一样的。但是他们在方式是有所区别的。
ApplicationContext VS BeanFactory
相同点:
- 都可以得到 Spring 的上下文对象
- 都是 Spring 容器的顶级接口 (都可以管理 bean 对象)
不同点:
- 在继承关系和功能上来说:ApplicationContext 属于 BeanFactory 的子类,BeanFactory 只具备最基础的管理 bean 对象的能力,而ApplicationContext 继承了 BeanFactory 自然就拥有了它的基本功能,除此以外,还拓展了更多的功能,如:国际化的支持、资源访问支持、以及事件传播等方面的支持。
- 从性能的角度上来说:ApplicationContext 获取的Spring 上下文对象加载的方式是启动后一次性将 Spring 容器中的所有的 bean 对象全部实例化在内存中,所以在后面获取 Bean 对象的时候非常的快;BeanFactory 获取的Spring 上下文对象加载的方式是在需要某个 Bean 对象的时候,再去加载(实例化)Bean对象,所以在获取 Bean 对象的时候会比较慢。
在Spring框架的历史版本中,从Spring 2.x版本的时候就有了ApplicationContext的接口,但是BeanFactory仍然是一个核心接口,没有被淘汰。
一直到Spring 3.1版本,官方已经开始推荐使用ApplicationContext接口来代替BeanFactory进行Bean的管理和实例化。原因是ApplicationContext在BeanFactory的基础上增加了更多的功能,比如国际化、事件发布、AOP引入、web环境支持等,能够更好地满足开发的需求。
ClassPathXmlApplicationContext 属于 ApplicationContext 的子类,拥有 ApplicationContext 的所有功能,是通过 xml 文件(存储 Bean 对象的文件)的配置来获取所有的 Bean 对象的容器。
4.2 获取指定的 Bean 对象
上一步我们获取了 Spring 的上下文对象,context 这个对象就是用来管理 Bean 对象的,如果我们需要获取某个具体的 Bean 对象,需要在上下文对象的基础上调用 getBean() 方法
getBean()方法是从Spring容器中获取Bean实例的核心方法。
当前给大家介绍的功能是读取Bean 对象:
通过Bean ID或Bean名称从 Spring 容器中获取指定的Bean定义,如果没有找到,则抛出异常。
//1. 获取 Spring 上下文对象,创建的时候需要配置 Spring 的配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("spring-test.xml");
//2. 从 Spring 上下文中取出某个 bean 对象
Dog dog = (Dog)context.getBean("dog");// dog是我们给 Dog 类的实例取得的标志(名字)
注意事项:
否则会抛出:NoSuchBeanDefinitionException 异常
4.2.1 getBean() 方法的使用
getBean() 方法有很多种重载的方法,我们也可以使用其他的方法来获取 Bean 对象。
1. 根据 bean 对象的 id (标志)来获取 【上文已经讲过】
// dog是我们给 Dog 类的实例取得的标志(名字)
Dog dog = (Dog)context.getBean("dog");
使用 bean对象的 id 来获取,Spring 上下文对象—— context 的返回值是 Object, 所以需要进行强制类型转换。
2. 根据类型来获取 Bean
Dog dog = context.getBean(Dog.class);
因为我们直接使用 bean 对象的类型来获取,所以我们无需手动强制类型转换,在获取的时候会自动强转。
3. 根据 bean 对象的 id (标志)+ 类型 获取 bean
Dog dog = context.getBean("dog",Dog.class);
第一种方法的第二种方法的区别在于:
当一个类被重复的注册到 spring-test.xml 的配置文件中时,只能使用根据 ID (名称) 来获取。
此时 Spring 容器中存储了 两个 Dog 类的实例(bean 对象)。
我们使用类型来获取 bean 对象并使用时的表现:
所以我们当同类型的对象被注册到 Spring 中多次时就会导致程序报错,此时我们应当使用 bean 对象的 ID (名称) 来获取。但是这种方式的缺陷在于 我们需要手动的进行强制类型转换(返回类型是 Object)
所以我们推荐的写法是使用第三种方法 :根据 bean 对象的 id (标志)+ 类型 获取 bean 对象。
4.3 使用 Bean 对象
上文也说到其实 Bean 对像就是普通的实例化的对象,Bean 对象只是一个名字罢了。所以Bean 对象的使用跟我们传统对象的使用并无差异:
public class App {
public static void main(String[] args) {
//1. 获取 Spring 上下文对象,创建的时候需要配置 Spring 的配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-test.xml");
//2. 使用类型从 Spring 容器中获取 bean 对象
Dog dog = context.getBean("dog",Dog.class);
//3. bean 对象的使用
dog.setName("哈巴狗");
dog.setAge(3);
dog.setSex("公");
dog.setColor("白色");
dog.cry();
System.out.println(dog.toString());
}
}
五、总结
1. Spring 是一个包含众多工具方法的 loC (控制反转)容器,属于第三方库,所以我们在使用 Spring 的时候需要为项目注入相关依赖,既然是容器就有两个最基本的功能,存储和取出。
2. 存储 Bean 对象
- 创建 Bean 对象 (就是普通类的实例化对象)
- 将Bean 对象注册(配置)到:Spring 的配置文件 【.xml 文件】
文件名是自定义的,但是尽量保持规范,在从 Spring 中取出 Bean 对象的时需要用到配置文件名。如何注入请看上文解析……
3. 获取 Bean 对象
- 获取 Spring 上下文对象(管理着 Bean对象)获得的方式有两种:ApplicationContext 接口(官方推荐),Beanfactory (老版本)
- 从上下文对象中获取某一个对象调用getBean() 方法,该方法有三种获取方式,根据bean 对象的 ID (标识)获取,根据 Bean 对象类型获取,缺点:第一个需要强制类型转换,第二个在出现同类型的 Bean 对象的时候程序会报错。所以推荐使用第三种做法: 根据 Bean 对象 ID 和 对象类型获取
- 获取到 Bean 对象后就可以正常的使用,与我们常规的用法一样
操作流程如下图所示:
白云蓝天,一伞嫣然。