经过前⾯的学习我们已经知道了,Spring 就是⼀个包含了众多⼯具⽅法的 IoC 容器。既然是容器那么 它就具备两个最基本的功能: 将对象(Bean)存储到容器(Spring)中; 从容器中将对象取出来。那么该怎么将Bean存储的Spring以及再将其拿出来使用呢??别着急其实很简单,只需要跟着学习就可以掌握。
目录
1. 创建Spring项目
1.1 创建一个Maven项目
1.2 添加Spring依赖(Maven国内源)
1.3 添加 Spring 框架⽀持
1.4 添加启动类
2.存储Bean对象
2.1 创建Bean
2.2 将Bean注册到容器当中
3. 获取并使用Bean对象
3.1 创建Spring上下文
3.3 使用Bean
4.总结
1. 创建Spring项目
接下来使⽤ Maven ⽅式来创建⼀个 Spring 项⽬,创建 Spring 项⽬和 Servlet 类似,总共分为以下 3 步:
- 1. 创建⼀个普通 Maven 项⽬。
- 2. 添加 Spring 框架⽀持(spring-context、spring-beans)。
- 3. 添加启动类。
1.1 创建一个Maven项目
按照下面的截图操作即可。
1.2 添加Spring依赖(Maven国内源)
这两个都要设置。前者是当前文件,后者是以后新建文件配置。
然后找到settings.xml
我的在C:\Users\用户名\.m2\下面,打开settings.xml。在<mirrors>里面加上下面的配置代码。
<!-- 阿里云仓库 -->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
1.3 添加 Spring 框架⽀持
在项⽬的 pom.xml 中添加 Spring 框架的⽀持,xml 配置如下:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.24.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.4 添加启动类
我们刚才创建好的项目此时应该已经成功创建,在java文件下创建一个启动类,包含main方法即可:
public class App {
public static void main(String[] args) {
}
}
2.存储Bean对象
既然一直在说Spring是一个包含众多工具的IoC容器,现在我们的Spring项目也创建好的,那么怎么将Bean对象存进Spring呢??听起来十分的高大上,其实也是很简单的套路。存储Bean可以分为两步:
- 1. 存储Bean之前,我们必须得现有Bean啊,因此先要创建一个Bean。
- 2. 将创建的Bean注册到Spring容器之中。
2.1 创建Bean
Bean,听起来很高级,其实就是Java中的一个普通的对象,我们可以简单实现一个:
public class Student {
public Student() {
System.out.println("Student无参构造");
}
public void play(){
System.out.println("我喜欢打篮球!");
}
}
2.2 将Bean注册到容器当中
在创建好的项⽬中添加 Spring 配置⽂件 spring-config.xml,将此⽂件放到 resources 的根⽬录下, 如下图所示:(鼠标右键新建file,文件名称spring-config.xml)
这里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"
xmlns:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
</beans>
然后就可以将刚才的Student类注册到Spring中了,怎么存呢?先介绍通过配置文件的方式来存储。具体的操作就是在刚才的配置文件中的<beans>中添加:
<bean id="student" class="com.spring.demo.Student"></bean>
3. 获取并使用Bean对象
获取并使⽤ Bean 对象,分为以下 3 步:
- 1. 得到 Spring 上下⽂对象,因为对象都交给 Spring 管理了,所以获取对象要从 Spring 中获取,那 么就得先得到 Spring 的上下⽂。
- 2. 通过 Spring 上下⽂,获取某⼀个指定的 Bean 对象。
- 3. 使⽤ Bean 对象。
3.1 创建Spring上下文
这里介绍两种方式来创建Spring上下文。
第一种就是使用ApplicationContext,实现代码如下:(ApplicationContext是接口 ClassPathXmlApplicationContext是它的一个实现类。)
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
第二种就是使⽤ BeanFactory 来作为 Spring 的上下⽂,如下代码所示:
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
这里第二种方式其实并不推荐,这是早期的用法,现在官方已经不推荐使用了,IDEA使用时会看到已经被划线了。既然提到了两种方式必然要做出比较,这也是一道十分常见的面试题。
ApplicationContext VS BeanFactory(常⻅⾯试题)
- 继承关系和功能⽅⾯来说:Spring 容器有两个顶级的接⼝:BeanFactory 和 ApplicationContext。其中 BeanFactory 提供了基础的访问容器的能⼒,⽽ ApplicationContext 属于 BeanFactory 的⼦类,它除了继承了 BeanFactory 的所有功能之外,它还拥有独特的特性, 还添加了对国际化⽀持、资源访问⽀持、以及事件传播等⽅⾯的⽀持(这几个支持通过后面的学习应该会提到,目前不展开说明)。
- 从性能⽅⾯来说:ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象,⽽ BeanFactory 是需要那个才去加载那个,因此更加轻量。
第一点很好理解,BeanFactory 是很早之前使用的接口,现在使用的ApplicationContext 是继承自BeanFactory所以除了具有父类的特点之外还具有自己的独特的特性。那么第二点ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象,⽽ BeanFactory 是需要那个才去加载那个,因此更加轻量怎么来理解呢??之后会从代码角度展示出来它们的区别。
3.2 获取指定的Bean对象
// 1.得到Spring ApplicationContext是接口 ClassPathXmlApplicationContext是它的一个实现类
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// Student student1 = new Student(); 传统方式----缺点已经讲过
// 2. 从Spring中获取Bean对象
//Student student = (Student)context.getBean("student"); // 根据名称获取 十分不推荐 而且使用了强转
//Student student = context.getBean(Student.class); // 根据类型获取 只有当此种类型的Bean有且只有一个的时候才可以使用
Student student = context.getBean("student", Student.class); // 根据名称和类型来获取对象
注意:
1. 通过context.getBean()来获取Bean的时候,Bean的ID要和配置文件里的ID一一对应:
2. 获取Bean的方法有很多这里提供了三种,他们是重载的关系,根据不同的场景来使用,当然更推荐第三种。第二种是通过类名来获取,当只存一个指定类的时候才可以使用,否则就会报错。第三种是通过名称+类型,这种方式是最靠谱最推荐的方式。如果一类类型的对象存入为两个不同的id使用Student student = context.getBean(Student.class)的时候就会报错。
3. 当一个类型被以不同的id注册进Spring时,两个Bean是同一个引用吗??比如
答案是:不是同一个引用。他们分别存放,是不同的地址。
Student student = context.getBean("student", Student.class); Student stu = context.getBean("stu", Student.class); System.out.println("stu == student??:"+(stu==student))
运行结果是false。
3.3 使用Bean
这里就是为了验证我们的Bean对象是否成功的被我们存进Spring中并且可以成功使用,因此不用设计太多的逻辑结构,直接利用我们获取到的Bean对象来调用它的共有方法,以此来验证是否成功。
student.play();
运行我们的APP:
此时发现的确成功的进行了Bean的存储和获取使用,在这里我们没有通过new的方式来实例化对象,之前也讲过这样new的方式来实例化的花会有诸多弊端。详情可以移步前一节的博客了解。博客链接。
现在我们存储和获取使用一套流程可以完整的走下来了,但是之前提到的ApplicationContext VS BeanFactory的问题还没有用代码来展示,现在可以用代码展示。怎么来设计代码呢?先看我们要证明的东西:ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象,⽽ BeanFactory 是需要那个才去加载那个。这样我们可以再配置文件中再存储一个Teacher类,然后再通过两种方式获取Student类只使用Student看看他们的区别。代码如下:
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 将com.spring.demo.Student类存储到Spring容器中,他的名字叫做student -->
<bean id="student" class="com.spring.demo.Student"></bean>
<!-- <bean id="stu" class="com.spring.demo.Student"></bean>-->
<bean id="teacher" class="com.spring.demo.Teacher"></bean>
</beans>
Studeant类和Teacher类:
public class Student {
public Student() {
System.out.println("Student无参构造");
}
public void play(){
System.out.println("我喜欢打篮球!");
}
}
public class Teacher {
public Teacher() {
System.out.println("teacher 无参数构造");
}
public void play(){
System.out.println("我喜欢打高尔夫!");
}
}
App:(Application方式获取)
public class App {
public static void main(String[] args) {
// 1. 得到Spring上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2. 从spring容器中获取bean对象
Student student = context.getBean("student", Student.class); // 根据名称和类型来获取对象
//3. 使用bean
student.play();
}
}
App2:(BeanFactory方式获取)
public class App2 {
public static void main(String[] args) {
// 1. 得到Spring上下文对象
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
// 2. 从spring容器中获取bean对象
Student student = (Student)beanFactory.getBean("student"); // 根据名称获取
//Student student = beanFactory.getBean(Student.class); // 根据类型获取
//3. 使用bean
student.play();
}
}
分别运行发现:
并且Application方式在
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
这一行代码运行后就会直接初始化所有的Bean对象,可以自己实验一下,将后面的代码注释掉也会执行Student和Teacher的构造方法。
4.总结
1. 操作容器之前,先要有容器,所以先要得到容器。
2. 存对象
- a. 创建 Bean(普通类)。
- b. 将 Bean 注册(配置)到 spring-confing.xml 中。
3. 取对象
- a. 得到 Spring 上下⽂,并读取到 Spring 的配置⽂件。
- b. 获取某⼀个 Bean 对象。
- c. 使⽤ Bean 对象。