1 了解Spring框架
1.1 框架
框架,特指为解决一个开放性问题而设计的具有一定约束性的基础架构。在此架构上可以根据具体问题进行扩展和定制,添加更多的组成部分,从而更迅速和方便地构建完整的解决问题方案。
框架,是一种可重用的设计,相当于一个半成品或者说模板,让使用者可以遵循框架的设计快速打造一个成品。
1.2 认识Spring框架
Spring框架:
-
Spring是一个JavaSE/EE的一站式轻量级开源框架
-
用于创建松散耦合和易测试的程序,解决企业开发的复杂性。
-
Spring是一个基于IoC思想和AOP思想的容器框架。IoC- 控制反转(Inversion of Control)、AOP-面向方面/切面编程(Aspect Oriented Programming)
-
使用Spring开发可以将Bean对象、Dao组件对象,Service组件对象等交给Spring容器来管理,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。
-
使用Spring框架,你不必编写大量的代码去实现框架已经实现的功能,很多事情都可以交给框架去做,如依赖的对象的实例化和注入(依赖注入)、事务的管理等。
1.3 Spring架构/模块
Spring模块化的框架,使用Spring可以只引入需要的模块,无需引入所有模块。
- Core Container: 框架核心模块,提供Spring框架基本功能,如IoC和DI支持
- Web: 提供Web开发支持
- AOP: 提供AOP支持
- Test: 支持单元测试和集成测试
2 IoC-控制反转
2.1 IoC理解
考虑如下代码:
public class A{
B b=new B1();
public void methodA(){
b.methodB();
}
}
A强依赖于B1-紧耦合:一个系统的不同组件之间紧密关联,存在强依赖关系
对这份代码做一个修改:
public class A{
B b;
public void methodA(){
b.methodB();
}
}
这里不再自己new B1的对象实现A对B1的弱依赖,实现松散耦合
于是我们可以有IoC的定义:
控制反转(IoC):将创建对象的权利交给框架(容器)管理,而不是自己new对象和管理对象。此外,框架可以根据依赖关系注入依赖的对象,开发者可以极大地从对象的管理中解脱出来。
DI(依赖注入) 是IoC思想的一个实现。
控制反转(IoC)不是一种技术,而是一种设计思想,指对一个对象的控制权的反转,主要是为了降低程序的耦合(coupling),也就是解耦(decoupling)
IoC的思想即为:
- 一般,多个对象合作完成一个功能,这样在一个对象里,就需要使用另一个对象,以前我们可以用new object() 这样的语法来完成合作对象的创建,但是这样,对象间的耦合度高了。
- IoC的思想是将程序对 对象 的控制权交给IoC容器
- 不在程序中new对象,而是交给Spring去创建和管理对象。从主动获取对象到被动接受对象
2.2 Spring IoC容器
Web应用程序由大量的程序组件组成,这些组件一起工作完成业务逻辑的执行。 这些组件通常是一个依赖另一个,互相协作实现所需功能。
Spring提供容器,也就是IoC容器,来管理这些组件,我们叫做Bean,Spring容器负责创建、初始化和销毁其管理的各种Bean,并根据Bean的依赖关系注入依赖的Bean,也就是依赖注入(DI)。
Spring IoC容器的类型:
- BeanFactory容器(Bean工厂容器):低级容器,提供容器的基本功能,包括Bean的管理和依赖注入。由org.springframework.beans.factory.BeanFactory接口表示
- ApplicationContext容器(应用程序上下文容器):高级容器,提供BeanFactory容器的功能,还提供一些高级的企业级功能。由org.springframework.context.ApplicationContext接口表示。如果没有什么特殊理由,直接使用ApplicationContext容器即可
2.2.1 BeanFactory容器
首先读取spring配置文件,封装成一个Resource对象,通过该对象使用配置文件。
- 如果spring配置文件放到了程序里,使用Resource接口的实现类ClassPathResource来加载spring配置文件
- 如果spring配置文件放到了文件系统中(如C盘),使用Resource接口的实现类FileSystemResource来加载spring配置文件
Resource resource=new ClassPathResource("config/beans.xml");
BeanFactory是个接口,其中常用的一个实现类是XmlBeanFactory。XmlBeanFactory是读取xml配置文件,加载BeanFactory容器。需要传入一个Resource对象,说明关联的spring配置文件是哪个
BeanFactory beanFactory=new XmlBeanFactory(resource);
在容器中,默认一个bean是单例的,不管请求整个bean多少次(如调用getBean()方法),返回的都是同一个实例。
在BeanFactory容器中,bean是在第一次请求的时候被实例化。
实例化的方法:
- 可以根据bean的id获取一个bean实例
- 可以根据bean的name(别名)获取一个bean实例
- 可以根据bean的类型获取一个bean实例,这样不需要转换类型
//1. 可以根据bean的id获取一个bean实例
Dog d1=(Dog)beanFactory.getBean("dog");
d1.eat();
//2. 可以根据bean的name(别名)获取一个bean实例
Dog d2=(Dog)beanFactory.getBean("gou");
d2.eat();
//3. 可以根据bean的类型获取一个bean实例,这样不需要转换类型
Dog d3=beanFactory.getBean(Dog.class);
d3.eat();
2.2.2 ApplicationContext容器
- 如果spring的xml配置文件在程序中,也就是类路径上,则使ClassPathXmlApplicationContext实现类
- 如果spring的xml配置文件在文件系统中(如c盘),则使用FileSystemXmlApplicationContext实现类
ApplicationContext ctx=new ClassPathXmlApplicationContext("config/beans.xml");
可以指定一个或多个spring配置文件,形成一个上下文容器,这样该容器管理多个配置文件中定义的bean
ApplicationContext ctx=new ClassPathXmlApplicationContext("config/beans1.xml","config/beans2.xml","config/beans2.xml");
在应用程序上下文容器中,容器启动,就会实例化所有的单例的bean。
默认情况下,一个bean是单例,也就是不管请求该bean多少次,返回的都是同一个实例。
实例化方法同BeanFactory容器
//1. 可以根据bean的id获取bean实例
Dog d1=(Dog)ctx.getBean("dog"); //2
d1.eat();
//2. 可以根据bean的name(别名)获取bean实例
Dog d2=(Dog)ctx.getBean("gou");
d2.eat();
//3.可以根据bean的类型获取bean实例
Dog d3=(Dog)ctx.getBean(Dog.class);
d3.eat();
3 配置Spring程序
Spring配置文件用于定义Spring管理的Bean(对象)。
3.1 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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 被spring管理的一个bean使用bean标记来定义 -->
<!-- class: 指定bean对应的类型的全限定名称 -->
<!-- id: 用于指定一个名称,作为该bean的唯一标识符,如果不需要id,也可不指定该属性 -->
<!-- name: 用于指定bean的别名,多个的使用空格或逗号或分号分割 -->
<bean id="dog" name="gou,quan,wang" class="com.qdu.bean.Dog" />
<!-- scope: 指定bean的范围,决定了bean实例化的数量 -->
<!--
有效值:
singleton: 默认值,单例,每次请求一个bean,返回的是同一个共享实例
prototype: 原型,每次请求一个bean,获取的是一个新的实例
其他值包括:request, session, application, websocket等,是在web程序中使用
-->
<bean id="pig" class="com.qdu.bean.Pig" scope="prototype" />
<!-- 如果不使用id,也可不指定id -->
<!-- 对于单例的bean,容器启动的时候就会实例化 ,如果将lazy-init设置为true
则单例的bean在第一次请求的时候被实例化
scope为prototype的bean在每次请求的时候被实例化
-->
<bean class="com.qdu.bean.Sheep" lazy-init="true" />
</beans>
<bean>:
- 被spring管理的一个bean使用bean标记来定义
- class: 指定bean对应的类型的全限定名称
- id: 用于指定一个名称,作为该bean的唯一标识符,如果不需要id,也可不指定该属性
- name: 用于指定bean的别名,多个的使用空格或逗号或分号分割
- scope: 指定bean的范围,决定了bean实例化的数量
- scope有效值:
singleton: 默认值,单例,每次请求一个bean,返回的是同一个共享实例
prototype: 原型,每次请求一个bean,获取的是一个新的实例
其他值包括:request, session, application, websocket等,是在web程序中使用 - lazy-init: 对于单例的bean,容器启动的时候就会实例化 ,如果将lazy-init设置为true,则单例的bean在第一次请求的时候被实例化。scope为prototype的bean在每次请求的时候被实例化