您现在的位置是:首页 >技术交流 >从 Spring 的创建到 Bean 对象的存储、读取网站首页技术交流
从 Spring 的创建到 Bean 对象的存储、读取
目录
ApplicationContext 和 BeanFactory 的区别:
创建 Spring 项目:
创建一个 Spring 项目分为四步:
- 创建一个普通 Maven 项目;
- 添加 Spring 框架支持;
- 配置资源文件;
- 添加启动类;
1.创建一个 Maven 项目:
前提声明:个人尽量使用 idea2021,因为2022版之后的相关插件是收费的;
2.添加 Spring 框架支持:
将这段配置依赖添加到 Spring 项目的 pom.xml 文件中:刷新下载到本地仓库
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.24</version>
</dependency>
</dependencies>
3.配置资源文件:
在 resources 包中创建一个 xxx.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">
<content:component-scan base-package="com.spring.demo"></content:component-scan>
</beans>
4.添加启动类:
在 java 文件下创建一个类,专门用来启动测试:
public class School {
public static void main(String[] args) {
}
}
Bean 对象的使用:
1.存储 Bean 对象:
原理:Spring 框架有 spring-context 来管理 spring 上下文,还有 spring-beans 来管理对象的模块;
什么是 Bean对象?项目中重复使用的对象都可以视为 Bean 对象,存储 Bean 对象也就是把项目所需的对象放入 Spring 容器中;
1.1 创建 Bean:
现在创建了一个普通的 Student 类,其自带一个 sayHi() 方法,由于以后我还要频繁使用这个类,那么就可以将其视为一个 Bean:
public class Student {
public void sayHi() {
System.out.println("hi student");
}
}
1.2 存储 Bean 到容器内:
存储bean也相当于“声明”的作用,先打开刚才在 resources包里创建的 spring-config.xml 配置文件:
存储 Bean 的格式:
<bean id="" class=""><bean>
如果 bean 在多级包内,class属性设置时就要注意路径;
现在将 Student 这个类作为 bean 添加进去:注意路径
<!-- 将Bean对象(com.spring.demo.com.spring.demo.Student)
存到 Spring容器中,它的 id 为 student-->
<bean id="student" class="com.spring.demo.Student"></bean>
2.获取 Bean 对象:
获取 bean 对象分为三步:
- 得到 Spring 上下文对象:因为 Bean 对象交给了 Spring 来管理,所以得先得到 Spring 才能有权限操作容器;
- 通过 Spring 上下文获取容器内的 Bean 对象;
- 使用 Bean 对象;
2.1 创建 Spring 上下文:
这里需要了解两个接口:ApplicationContext 和 BeanFactory;
语法:
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
BeanFactory beanFactory =
new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
2.2 获取指定 Bean 对象:
这里借助 ApplicationContext 来演示:
public class School {
public static void main(String[] args) {
// 1.得到 Spring 上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.获取指定 Bean 对象
Student student = (Student) context.getBean("student");
// 3.使用 Bean 对象
student.sayHi();
}
}
至此 Spring 的创建、Bean 的存储和获取已经做了基本介绍;
ApplicationContext 和 BeanFactory 的区别:
在上述代码中再添加一个 Teacher 类作为一个新的 Bean,添加到容器中:
public class Teacher {
public Teacher() {
System.out.println("do teacher init");
}
public void sayHi() {
System.out.println("hi teacher");
}
}
<bean id="student" class="com.spring.demo.Student"></bean>
<bean id="teacher" class="com.spring.demo.Teacher"></bean>
此时我们的容器中有两个 Bean:一个是Student、一个是Teacher;
分别使用 ApplicationContext 和 BeanFactory 来操作:都只尝试获取容器中 Student 这个 Bean,来看看它们的效果有什么不同.
ApplicationContext:
原代码不用变:
public class School {
public static void main(String[] args) {
// 1.得到 Spring 上下文
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.获取指定 Bean 对象
Student student = (Student) context.getBean("student");
// 3.使用 Bean 对象
student.sayHi();
}
}
BeanFactory:
创建一个新的启动类:School2,获取 Spring 上下文和 ApplicationContext 不一样,其他也不用变。
public class School2 {
public static void main(String[] args) {
// 1.使用 BeanFactory 来获取 Spring 上下文
BeanFactory beanFactory =
new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
// 2. 从 Spring 容器中获取 bean 对象
Student student = (Student) beanFactory.getBean("student");
student.sayHi();
}
}
对比运行结果,明明它们两个都时获取和使用 id 为 “student” 的 Bean 对象,ApplicationContext 对于上下文却把 Teacher 也拿了出来,BeanFactory 只拿到了 Student;
总结:
相同点:
- ApplicationContext 和 BeanFactory 都是获取容器中Bean对象的;
不同点:
- ApplicationContext 是一次性加载并初始化容器里的所有 Bean 对象(饿汉模式),而 BeanFactory 是需要哪个才去加载哪个(懒汉模式);
- ApplicationContext 其实是 BeanFactory 的子类,子类不仅继承了父类的所有功能外,还拥有自己独特的功能;而ClassPathXmlApplicationContext 又属于 ApplicationContext的子类;
- BeanFactory 也是最早被设计出来的,设计之初由于机器硬件造价昂贵,就只加载需要的对象;而 ApplicationContext 是之后设计出来的,人们为了尽可能提高效率,就想到一次性加载出所有 Bean 对象;
三种常用的 getBean :
getBean() 方法有很多重载,对比以下常用的三种:
- 根据 id 获取;
- 对象类型获取;
- id,对象类型获取;
根据 id 获取:
<bean id="student" class="com.spring.demo.Student"></bean>
<bean id="teacher" class="com.spring.demo.Teacher"></bean>
// 2.获取指定 Bean 对象
Student student = (Student) context.getBean("student");
Teacher teacher = (Teacher) context.getBean("teacher");
这种方式显然比较粗暴,不可取,存在强转;另外如果通过id获取的对象为null,也会出现异常;
对象类型获取:
<bean id="student" class="com.spring.demo.Student"></bean>
<bean id="teacher" class="com.spring.demo.Teacher"></bean>
// 2.获取指定 Bean 对象
Student student = context.getBean(Student.class);
Teacher teacher = context.getBean(Teacher.class);
这种方式虽然不粗暴,但存在一个问题:
当同一类型的 Bean 在容器中注册了两次,编译器就会报 NoUniqueBeanDefinitionException 异常;
id + 对象类型获取:
这种方式安全性较高;
<bean id="student" class="com.spring.demo.Student"></bean>
<bean id="student2" class="com.spring.demo.Student"></bean>
<bean id="teacher" class="com.spring.demo.Teacher"></bean>
// 2.获取指定 Bean 对象
Student student = context.getBean("student2",Student.class);
Teacher teacher = context.getBean("teacher",Teacher.class);
思考:
既然刚才提到了同一个类型可能在容器中注册多次,虽然它们只是 id 不同,那它们指向的是否为同一块空间呢?
代码验证一下:
<bean id="student" class="com.spring.demo.Student"></bean>
<bean id="student2" class="com.spring.demo.Student"></bean>
<bean id="teacher" class="com.spring.demo.Teacher"></bean>
public class School {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Student student1 = context.getBean("student", Student.class);
Student student2 = context.getBean("student2", Student.class);
System.out.println(student1 == student2);
System.out.println(student1.equals(student2));
}
}
于是证明它们本身就是不同的对象的引用;
总结:
Spring 项目的创建及 Bean 的基本使用流程: