【SSM详细教程】-01-Spring容器以及配置详解
精品专题:
01.C语言从不挂科到高绩点
https://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482https://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482
02. SpringBoot详细教程
https://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.5482https://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.548203.SpringBoot电脑商城项目
https://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.5482https://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.548204.VUE3.0 核心教程
https://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482https://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482
================================
|| 持续分享系列教程,关注一下不迷路 ||
|| 视频教程:小破站:墨轩大楼 ||
================================
一、Spring简介
Spring是一个开源的轻量级应用开发框架,其目的用于简化企业级应用程序开发,减少侵入。要注意,这里的轻量级指的并不是类的数量或者发布的大小,而是整体性定义Spring原则:最轻的影响。从某种意义上讲,Spring是轻量级的,因为只需要对应用程序代码进行很少的更改,就可以获得SpringCore所带来的好处,如果想要在任何时候停止使用Spring,那么会发现可以很容易做到。Spring框架能够很好的解决企业级系统面临的问题。
1.1 企业级系统特点
- 大规模:用户数量多、数据规模大、功能众多
- 性能和安全要求高
- 业务复杂,需要灵活应变
Spring 提供的IOC和AOP应用,可以将组件的耦合度将至最低,即解耦。便于系统后期的维护和升级。同时Spring也为系统提供了一个整体的解决方案,开发者可以利用它本身提供的功能外,也可以与第三方框架和技术整合应用,可以自由选择采用哪种技术进行开发。
Spring 被称为Java EE的春天,是当前主流框架。
Spring的体系结构如下图所示:
1.2 Spring 的优点
- 低侵入式设计。
- 独立于各种应用服务器。
- 依赖注入特性将组件关系透明化,降低了耦合度。
- 面向切面编程特性允许将通用任务进行集中式处理。
- 和第三方框架可以很好的进行整合。
1.3 Spring 的核心功能
Spring 是面向Bean的编程。在Spring中,任何的Java类和JavaBean都被当成Bean处理,这些Bean通过Spring容器管理和应用。Spring容器提供了以下两个核心功能机制来简化Bean对象创建和Bean对象之间的解耦。
- IOC (Inversion Of Control ):控制反转 / DI(Dependency Injection):依赖注入
- AOP(Aspect Oriented Programming):面向切面编程
Spring容器有BeanFactory和ApplicationContext两种类型。所谓的JavaBean,其实就是一种简单规范的Java对象。当需要管理JavaBean对象时候可以使用Spring。Spring是最简介的对象管理方案之一。
1.4 Spring容器的实例化
1.4.1 idea中创建Spring项目
1.4.2 在pom.xml中添加如下依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
1.4.3 在resource中新建Spring配置文件 application.xml
创建后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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
1.4.4 在test中新建测试类,测试Spring容器初始化
package day01;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest01 {
@Test
public void test01(){
ApplicationContext context =
new ClassPathXmlApplicationContext("application.xml");
System.out.println(context);
}
}
运行效果为:
二、Spring 容器的使用
从本质上讲,BeanFactory和ApplicationContext仅仅只是一个维护Bean定义以及相互依赖关系的高级工厂接口。通过BeanFactory和ApplicationContext我们可以访问bean定义。
首先在容器配置文件applicationContext.xml中添加Bean定义。
<bean id="标识符" class="Bean类型"/>
然后在创建BeanFactor和ApplicationContext容器对象后,调用getBean() 方法获取Bean的示例。
2.1 Bean的实例化
Spring容器创建Bean对象的方法 有以下3种:
- 用构造器来实例化
- 使用静态工厂方法实例化
- 使用实例工厂方法实例化
我们只需要将对象创建规则告诉Spring,Spring会帮助我们去创建对象。
2.1.1 用构造器来实例化
<!-- 构造器实例化对象 id指定名称-->
<bean id="calendarObj" class="java.util.GregorianCalendar"></bean>
<!-- 构造器实例化对象,name指定名称-->
<bean name="dateObj" class="java.util.Date"></bean>
- id 或name属性用于指定Bean名称,用于从Spring种查找这个Bean对象。
- class 用于指定Bean类型,会自动调用无参构造器创建对象。
2.1.2 使用静态工厂方法实例化
<bean id="calendarObj2" class="java.util.Calendar"
factory-method="getInstance"></bean>
- id 属性用于指定Bean名称
- class 属性用于指定工厂类型
- factory-method 属性用于指定工厂中创建Bean对象的方法,必须用static修饰的方法。
2.1.3 使用实例工厂方法实例化
<bean id="calendarObj3" class="java.util.GregorianCalendar"></bean>
<bean id="dateObj2" factory-bean="calendarObj3"
factory-method="getTime"></bean>
- id 用于指定Bean名称
- factory-bean属性用于指定工厂Bean对象
- factory-method属性用于指定工厂中创建Bean对象的方法。
测试方法:
/**
* 测试Bean实例化3种方式
*/
@Test
public void test02(){
// 初始化Spring容器
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 构造器实例化
Calendar calendar01 = (Calendar) context.getBean("calendarObj"); // 通过id去找
// 除了强制类型转换以外,也可以在方法中指定Bean的类型
Calendar calendar_1 = context.getBean("calendarObj",Calendar.class);
System.out.println("calendar:"+calendar01);
System.out.println("calendar:"+calendar_1);
Date date = (Date)context.getBean("dateObj"); // 通过name去Spring容器去找
System.out.println("date:"+date);
// 静态工厂实例化
Calendar calendar02 = context.getBean("calendarObj2",Calendar.class);
System.out.println(calendar02);
//实例工厂实例化
Date date02 = context.getBean("dateObj2",Date.class);
System.out.println(date02);
}
注意:
- 在Spring容器中,每个Bean都需要用名字,该名字可以用<bean>元素的id或者name属性指定。
- id属性比name严格,要求具有唯一性,不允许使用“/”等特殊字符。
2.2 Bean 的作用域
Spring容器在实例化容器时,可以创建以下作用域的Bean对象:
作用域 | 描述 |
singleton | 在每一个SpringIOC容器中,一个Bean对象定义对应一个对象实例 |
prototype | 一个Bean定义对应多个对象 |
request | 在一次HTTP请求中,一个Bean定义对应一个实例,仅限于Web环境 |
session | 在一个HTTPSession中,一个Bean定义对应一个实例,仅限于Web环境 |
global Session | 在一个全局的HTTPSession中,一个bean定义对应一个实例,仅在基于portlet的Web应用中才有意义,protlet规范定义了全局Session的概念。 |
上面的Bean作用域,可以通过<bean>定义的scope属性指定。
2.2.1【案例】 测试singleton作用域
在applicationContext.xml中添加如下Bean定义:
<!-- 默认是 singleton-->
<bean id="calendar01" class="java.util.GregorianCalendar"></bean>
在测试类中添加测试方法
@Test
public void test03(){
// 初始化Spring容器
ApplicationContext context =
new ClassPathXmlApplicationContext(
"applicationContext.xml");
Calendar calendar01 =
context.getBean("calendar01",Calendar.class);
Calendar calendar02 =
context.getBean("calendar01",Calendar.class);
System.out.println(calendar02==calendar01);
}
运行后会发现比较结果为true,说明两次获得的对象是同一个对象。
2.2.2【案例】测试prototype作用域
applicationContext.xml中添加如下Bean定义:
<bean id="calendar02"
class="java.util.GregorianCalendar"
scope="prototype"></bean>
在测试类中添加测试方法
Calendar calendar03 =
context.getBean("calendar02",Calendar.class);
Calendar calendar04 =
context.getBean("calendar02",Calendar.class);
System.out.println(calendar04==calendar03);
运行后会发现结果为false,说明两次获得的对象不是同一个对象。
2.3 Bean生命周期
Spring容器在创建Bean时,可以帮忙管理Bean的生命周期,即管理bean的初始化及销毁的方法。
默认情况下Spring容器创建时,会创建单例的对象,也可以让spring容器延迟实例化这些单例对象。
- 可以通过Bean标签的init-method属性指定初始化回调方法。
- 可以通过Bean标签的destory-method属性指定销毁回调方法,但是请注意,指定销毁回调方法,仅适用于singleton模式的bean。
2.3.1【案例】 Bean生命周期探索
在entity包中新建Hero类
package com.moxuan.spring01.entity;
import java.io.Serializable;
public class Hero implements Serializable {
public Hero(){
System.out.println("实例化Hero对象:"+this);
}
public void init(){
System.out.println("实例化Bean对象");
}
public void destroy(){
System.out.println("销毁Bean对象");
}
public void execute(){
System.out.println("执行execute方法");
}
}
在applicationContext.xml中添加bean
<bean id="heroObj" class="com.moxuan.spring01.entity.Hero"
destroy-method="destroy"
init-method="init" ></bean>
编写测试方法
@Test
public void test04(){
AbstractApplicationContext context =
new ClassPathXmlApplicationContext(
"applicationContext.xml");
System.out.println("------------------------------------------------------");
Hero hero = context.getBean("heroObj",Hero.class);
hero.execute();
context.close();
}
运行结果:
然后我们将bean的作用域切换成prototype,如下所示:
<bean id="heroObj" class="com.moxuan.spring01.entity.Hero"
destroy-method="destroy"
scope="prototype"
init-method="init" ></bean>
再次运行测试方法,结果如下:
可以发现控制台并没有输出预期的“销毁 Bean对象”的结果,原因在于设置destroy-method属性仅仅对singleton单例模式器作用,在prototype模式下没有意义。
2.4 Bean延迟实例化
从上面的案例中我们可以发现,在ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化。
如果不想让一个Singleton bean在ApplicationContext初始化时被提前实例化,可以使用<bean>标签的lazy-init="true"属性来实现。
一个延迟初始化的bean将在第一次被使用时被实例化。
修改上一个案例中的applicationContext.xml,添加延迟实例化属性,如下:
<bean id="heroObj" class="com.moxuan.spring01.entity.Hero"
destroy-method="destroy"
lazy-init="true"
init-method="init" ></bean>
再次运行测试方法,结果如下:
我们可以发现,对象会在第一次使用时才会创建。
2.5 指定Bean依赖关系
当一个bean对另一个bean存在依赖关系时,可以使用<bean>元素的depends-on属性指定。
【案例】 测试Bean依赖关系
添加一个武器类
package com.moxuan.spring01.entity;
public class Weapon {
public Weapon(){
System.out.println("实例化Weapon对象:"+this);
}
}
修改applictationContext.xml,让Hero依赖Weapon,代码如下所示:
<bean id="heroObj" class="com.moxuan.spring01.entity.Hero"
destroy-method="destroy" lazy-init="true"
init-method="init"
depends-on="weapon"></bean>
<bean id="weapon" class="com.moxuan.spring01.entity.Weapon"
lazy-init="true"></bean>
测试方法代码如下:
@Test
public void test04(){
AbstractApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("------------------------------------------------------");
Hero hero = context.getBean("heroObj",Hero.class);
hero.execute();
context.close();
}
运行效果:
当一个Bean对多个bean存在依赖关系时,depends-on属性可以指定多个Bean名,用逗号隔开。
【案例】测试依赖多个Bean
新增一个Tools工具类
public class Tools {
public Tools(){
System.out.println("实例化Tools对象:"+this);
}
}
在applicationContext.xml中添加tools的bean,并修改hero的bean,具体代码如下:
<bean id="heroObj" class="com.moxuan.spring01.entity.Hero"
destroy-method="destroy" lazy-init="true"
init-method="init"
depends-on="weapon,tools"></bean>
<bean id="weapon" class="com.moxuan.spring01.entity.Weapon"
lazy-init="true"></bean>
<bean id="tools" class="com.moxuan.spring01.entity.Tools"
lazy-init="true"></bean>
运行测试方法,测试结果为: