软件环境
JDK1.8+
Maven3.6+
IDEA2022.3(Ultimate Edition)
Spring5.3.29
主要知识点大纲
1.Spring简介
2.Spring整体架构
3.业务场景中理解Spring IOC(控制反转)和DI(依赖注入)
4.业务场景中理解IOC容器,实例化容器,实例化Bean的几种方式
5.业务场景中理解Bean依赖注入(DI)的几种方式
说明:文档中的业务对象都来自于旅游和支付行业
先学会使用Spring各种特性和功能,然后再通过手写Spring掌握原理和设计思想
1.Spring是什么
顾名思义Spring是春天的意思,春天代表万物复苏,生机盎然。代表着Spring能给Java行业带来活力和生机,那如何能带来活力和生机呢? Spring框架生态庞大,现在已经成为Java企业级应用开发一整套解决方案,另外大大简化了企业级应用开发的难度和提高了开发的效率。
Spring 2003年由Rod Johnson(罗宾·约翰逊)创建,从Spring Framework 5.1开始,Spring需要JDK 8+(Java SE 8+),并为JDK 11 LTS提供开箱即用的支持。建议将Java SE 8更新60作为Java 8的最低补丁版本,但通常建议使用最新的补丁版本。
2.Spring整体架构
3.Spring框架中的两个核心思想
3.1 IOC(Inversion of Control) 控制反转
业务场景中的IOC
在没有IOC之前我们如果要到景区去游玩,必须得到景区所在地去购买门票。如果有了IOC之后我们就不需要到景区所在地购买门票了,只需要交由旅行社或者通过在线订票网站购买即可,那么这个时候购买门票的行为就发生了反转,原来购买门票是自己亲自购买,现在则交给了导游或者通过在线订票网站购买。我们Spring中的控制反转是什么呢?原来Java对象的创建本来是由用户自己去创建,那么现在对象的创建交由Spring IOC容器来创建了。
3.2 DI(Dependency Injection)依赖注入
IOC思想中一个核心的概念就是DI(Dependency Injection)依赖注入
业务场景中的DI
游客购买好门票后要到景区去游玩,进入景区的过程中其实就产生了DI(依赖注入)
游客入园需要门票,游客去景区游玩不是单独存在的必须依赖于第三个事物(门票)才能完成,也就是完成一件事情必须相互配合才能完成。Spring可以把完成一件事件需要依赖的对象自动的注入到当前对象中。
4.IOC容器
4.1 什么是IOC容器
在Spring框架中容器是用于存放Java对象,在Spring中对象统一称为Spring Beans,一个对象就是一个Spring Bean,Bean是IOC容器中的最小单位。
4.2 业务场景中理解IOC容器
如果把游客游玩的景区(scenic)理解为IOC容器,那么游客,门票,游乐设施,景区内的剧场、餐厅,商店等等对象都是IOC容器中的Bean。
5.实例化容器
代码中用到的Bean对象有游客(Traveller)、门票(Ticket)、订单(Order)
创建Spring项目
5.1 Spring IOC容器重要基础
//对bean进行管理
org.springframework.beans
//对容器进行管理
org.springframework.context
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.29</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.29</version>
</dependency>
BeanFactory接口提供了一种高级配置机制,能够管理任何类型的对象。ApplicationContext是BeanFactory的一个子接口,ApplicationContext接口就是我们的IOC容器
<?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>
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
5.2 容器的使用
// create and configure beans 创建和配置bean
// 实例化景区(IOC容器)scenicContext
ApplicationContext scenicContext = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
// retrieve configured instance 检索配置实例 实例化游客
TravellerService travellerService = context.getBean("travellerService", TravellerService.class);
/** ticketService入园 use configured instance 使用IOC容器中的实例*/
Boolean success = travellerService.enteringPark();//游客在入园
<bean id="travellerService" class="cn.itbeien.service.TravellerService"/>
<bean name="ticketService" class="cn.itbeien.service.TicketService"/>
6.实例化Beans-XML方式
6.1 使用构造方法进行实例化
<bean id="travellerService" class="cn.itbeien.service.TravellerService"/>
<bean name="ticketService" class="cn.itbeien.service.TicketService"/>
6.2 使用静态工厂方法进行实例化
<bean id="travellerService"
class="cn.itbeien.service.TravellerService"
factory-method="createInstance"/>
package cn.itbeien.service
public class TravellerService {
private static TravellerService travellerService = new TravellerService();
private TravellerService() {}
public static TravellerService createInstance() {
return travellerService;
}
}
6.3 使用工厂方法进行实例化
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="travellerService" class="cn.itbeien.service.TravellerService">
<!-- inject any dependencies required by this locator bean -->
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="ticketService"
factory-bean="travellerService"
factory-method="createTicketServiceInstance"/>
public class TravellerService {
private static TicketService ticketService = new TicketService();
public TicketService createTicketServiceInstance() {
return ticketService;
}
}
一个工厂类也可以容纳一个以上的工厂方法,如下例所示
<!-- the factory bean, which contains a method called createInstance()
工厂bean,它包含一个名为createInstance()的方法
-->
<bean id="travellerService" class="cn.itbeien.service.TravellerService">
<!-- inject any dependencies required by this locator bean
注入此工厂bean所需的任何依赖项
-->
</bean>
<!-- the bean to be created via the factory bean
通过工厂bean创建的bean
-->
<bean id="ticketService"
factory-bean="travellerService"
factory-method="createTicketServiceInstance"/>
<bean id="orderService"
factory-bean="travellerService"
factory-method="createOrderServiceInstance"/>
public class TravellerService {
private static TicketService ticketService = new TicketService();
private static OrderService orderService = new OrderService();
public TicketService createTicketServiceInstance() {
return ticketService;
}
public OrderService createOrderServiceInstance() {
return orderService;
}
}
7.DI(依赖注入)的几种方式
7.1 基于构造方法的注入
public class TravellerService {
/** the TravellerService has a dependency on a TicketService TravellerService依赖于TicketService
*/
private final TicketService ticketService;
/** a constructor so that the Spring container can inject a TicketService 构造函数,以便Spring容器可以注入TicketService
*/
public TravellerService(TicketService ticketService) {
this.ticketService = ticketService;
}
/** business logic that actually uses the injected TicketService is omitted... 省略了实际使用注入的TicketService的业务逻辑*/
}
<beans>
<bean id="travellerService" class="cn.itbeien.service.TravellerService">
<constructor-arg ref="ticketService"/>
<constructor-arg ref="orderService"/>
</bean>
<bean id="ticketService" class="cn.itbeien.service.TicketService"/>
<bean id="orderService" class="cn.itbeien.service.OrderService"/>
</beans>
7.2 基于set方法的注入
public class TravellerService {
/** the TravellerService has a dependency on the TicketService
TravellerService依赖于TicketService
*/
private TicketService ticketService;
/** a setter method so that the Spring container can inject a TicketService
一个setter方法,以便Spring容器可以注入TicketService
*/
public void setTicketService(TicketService ticketService) {
this.ticketService = ticketService;
}
/** business logic that actually uses the injected TicketService is omitted...
省略了实际使用注入的TicketService的业务逻辑…
*/
}
<bean id="TravellerService" class="cn.itbeien.service.TravellerService">
<!-- setter injection using the nested ref element
使用嵌套ref元素的Setter注入
-->
<property name="ticketService">
<ref bean="ticketService"/>
</property>
<!-- setter injection using the neater ref attribute
使用更简洁的ref属性的Setter注入
-->
<property name="orderService" ref="orderService"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="ticketService" class="cn.itbeien.service.TicketService"/>
<bean id="orderService" class="cn.itbeien.service.OrderService"/>
public class TravellerService {
private TicketService ticketService;
private OrderService orderService;
private int i;
public void setTicketService(TicketService ticketService) {
this.ticketService = ticketService;
}
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
public void setIntegerProperty(int i) {
this.i = i;
}
}
7.3 懒加载Bean
默认情况下Spring容器启动时就会创建被它管理的Bean,但是有的时候被Spring管理的Bean并不需要再容器启动的时候被创建,而是当前对象第一次被访问的时候进行创建,这种场景就可以使用懒加载实现。
业务场景
代码实现
<!-- 剧场使用懒加载-->
<bean id="lazy" class="cn.itbeien.service.TheaterService" lazy-init="true"/>
<!-- 负责验票的设备闸机不使用懒加载-->
<bean name="not.lazy" class="cn.itbeien.service.GateMachineService"/>