经过前面的学习我们已经大体明白了 IOC 思想以及它的实现方式 DI ,本节要讲的是如何Spring框架实现实现DI。
本节目标:
- Spring(Core) 项目创建
- 将对象存储到 Spring 中
- 将对象(bean)从 Spring 中取出
1. 创建 Spring 项目
与开篇演示的 Spring Boot 项目不同,罗马城不是一天建成的,Spring Boot 出来之前还是需要使用 Maven 构建一个 Spring 项目,与 Servlet 类似,但由于 IOC 和 DI 的加持,又更胜Servlet一筹,Spring 项目的创建分为以下三步:
- 创建一个普通Maven项目;
- 添加Spring框架依赖 spring-context、spring-beans(可以将spring-context理解为Spring本身,存储在Spring称之为bean,也就是spring-beans);
- 添加启动类;
1.1 创建Maven项目
1.2 添加Spring 框架依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.9.RELEASE</version>
</dependency>
添加完依赖记得检查一下:
1.3 添加启动类
2. 存储Bean对象
并不是真的存储,而是告诉Spring,此Bean需要托管给Spring
2.1 创建bean对象
Bean对象其实就是Java语言中的一个普通对象
public class UserBean {public void sayHi() {System.out.println("Hi!");}
}
2.2 创建配置文件
在resource目录下创建一个xml配置文件,取名随意
固定格式为以下内容,直接复制即可:
<?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>
2.3 注册bean
<bean id="user" class="UserBean"></bean>
解释:bean的id是自己命名的,命名规范同样是小驼峰,取bean的时候会用到。class对应的就是自己创建的bean对象(包名+类名),我这里没有放包里,因此直接就是UserBean
3. 从 Spring 中取出 bean对象
3.1 得到Spring的上下文对象
public class Application {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");}
}
ApplicationContext是一个接口,ClassPathXmlApplicationContext是它的实现类,由此得到Spring context对象
3.2 从Spring上下文中取出对象
getbean有如下这么多方法,这里先用最简单的通过beanId来获取bean对象:
//getbean方法里面的参数就是配置文件中bean对象的id
UserBean user = (UserBean)context.getBean("user");
3.3 使用bean对象
至此我们全程都没有使用过new对象的方式,成功从Spring中取出bean对象
3.4 理解bean的实例化
根据bean的class来获取bean
//1.根据一个String 参数获取bean
//UserBean user = (UserBean)context.getBean("user");
//2.根据一个Class 参数获取bean
UserBean user = context.getBean(UserBean.class);
由于传了UserBean.class这种方法不需要强转就能获取到bean,运行结果:
修改配置文件:
<bean id="user1" class="UserBean"></bean>
<bean id="user2" class="UserBean"></bean>
报错了,意思大概是找到了预料之外的两个bean对象user1、user2:
我们用第一种方式来查看一下两个bean对象的地址:
UserBean user1 = (UserBean)context.getBean("user1");
UserBean user2 = (UserBean)context.getBean("user2");
System.out.println("user1:" + user1);
System.out.println("user2:" + user2);
结果发现bean的id不同,即便他们是一个类,还是会实例化两个对象:
区分单例模式:单例模式指的是每一个bean对象都是单例的,而不是说一种类只能存在一个bean对象。
//取两次id为user1的bean,地址一样
UserBean user1 = (UserBean)context.getBean("user1");
UserBean user1Test = (UserBean)context.getBean("user1");UserBean user2 = (UserBean)context.getBean("user2");System.out.println("user1:" + user1);
System.out.println("user1Test:" + user1Test);
System.out.println("user2:" + user2);
结果发现确实是单例的:
4. Spring上下文对象
ApplicationContext context= new ClassPathXmlApplicationContext("spring-config.xml");
除了上面的那种写法,获取上下文对象还可以用下面这种写法——BeanFactory:
BeanFactory context = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
ApplicationContext 和 BeanFactory 的关系(面试常考)
共同点:都是用来获取Spring上下文对象
不同点:
- 继承和功能:ApplicationContext 是 BeanFactory 的子接口,ApplicationContext具备了BeanFactory的所有功能。BeanFactory 只具备最基础访问bean的能力,ApplicationContext 具备更多能力,比如国际化支持、资源访问支持、以及事件传播等方面的支持。
- 性能和加载方式 :ApplicationContext是饿汉模式一次性加载完所有Bean对象,BeanFactory是懒汉模式按需加载,更加轻量。随着硬件资源的升级,在资源充裕的情况下推荐使用ApplicationContext,使用户第一次使用bean对象时节省实例化bean对象并存储到Spring的开销。
5. 总结
Spring的创建和使用的过程:
- 创建Spring项目
- 创建一个 Maven 项目
- 添加 Spring 依赖
- 创建一个启动类
- 将对象存储到 Spring
- 创建一个 bean 对象
- 创建配置 .xml 文件
- 将 bean 注册到 Spring 的配置文件(id用于取对象,class表示存储bean的位置)
- 从Spring中取出 bean 对象
- 先得到 Spring 上下文对象
- 从 Spring 中取出bean对象并使用
这样使用Spring让我们初步理解到了DI的实现方式,但是我们发现并不便利,下一章节我们学习使用Spring的注解方式,让Spring框架更加简洁好用。