
第一章 Spring 框架介绍
1.1 框架概述
Spring 是2003 年 由 Rod Johnson 推出的开源、轻量级 Java 一站式(full-stack)框架,理念来源于其著作《Expert One-On-One J2EE Development and Design》,专为解决企业级应用开发复杂度而生。
核心特点
- 分层架构:模块化设计,开发者可按需选用组件,无缝整合 JavaEE 各类技术。
- 核心思想 :贯穿面向接口编程,实现层与层之间松耦合。
- 两大核心机制
- IOC(控制反转) :将对象创建、管理工作交给 Spring 容器,不再手动
new对象。 - AOP(面向切面编程):在不修改原有源代码的前提下,对方法进行功能增强(日志、权限、监控等)。
- IOC(控制反转) :将对象创建、管理工作交给 Spring 容器,不再手动
1.2 Spring 框架优点
- 解耦简化开发 依托 IOC 容器统一管理所有对象与依赖关系,彻底降低代码耦合度。
- 支持 AOP 编程 便捷实现权限拦截、运行监控、日志记录等通用功能。
- 声明式事务 通过配置即可完成事务管理,无需手动编写事务代码。
- 测试便捷 完美兼容 JUnit4,借助注解快速完成单元测试。
- 框架兼容性强 原生支持整合 Struts2、Hibernate、MyBatis 等主流开源框架。
- 简化 JavaEE API 对 JDBC、JavaMail 等复杂原生 API 进行封装,大幅降低使用难度。
第二章 Spring HelloWorld 入门案例
2.1 环境准备:Maven 导入依赖
创建 Maven 工程,在 pom.xml 中引入 Spring 核心、日志、单元测试依赖:
<dependencies>
<!-- Spring核心容器 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- 日志依赖 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
2.2 编写业务 Demo 类
package com.qcby.service;
public class Demo {
public void hello() {
System.out.println("hello world");
}
}
2.3 编写 Spring XML 配置文件
在 resources 目录下创建 applicationContext.xml(Spring 标准配置文件名),使用 <bean> 标签交由 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">
<!--
id:Bean唯一标识,用于容器中获取对象
class:类的全限定类名(包名+类名)
-->
<bean id="demo" class="com.qcby.service.Demo" />
</beans>
2.4 编写测试代码
对比传统创建对象 和 Spring 容器获取对象两种方式:
package com.qcby.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceTest {
// 传统方式:手动new对象,耦合度高
@Test
public void run(){
Demo demo = new Demo();
demo.hello();
}
// Spring方式:从IOC容器获取对象
@Test
public void run1(){
// 1. 加载配置文件,初始化Spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 根据id获取容器中的Bean对象
Demo demo = (Demo) ac.getBean("demo");
// 3. 调用方法
demo.hello();
}
}
第三章 Spring IOC 容器
3.1 IOC 思想概述
- 全称 :Inverse of Control,控制反转。
- 核心:将对象创建、依赖管理的控制权从开发者代码中转移给 Spring IOC 容器。
- 解决问题:消除代码之间硬依赖,大幅降低程序耦合度。
传统开发中,A 类主动 new B 类,层级依赖复杂时一处出错整体瘫痪;使用 IOC 后,所有对象统一由容器创建,业务代码仅需调用容器对象,解除硬绑定。
3.2 IOC 容器底层三大核心技术
- DOM4J :解析 XML 配置文件,读取
bean标签信息; - 工厂模式:统一工厂生产对象,解耦调用方与目标类;
- Java 反射:运行时根据全类名动态创建对象。
简易模拟 IOC 工厂
public class DemoFactory {
public static Demo getDemo() throws Exception {
// 1. DOM4J解析XML,拿到类全路径
String classPath = "com.qcby.service.Demo";
// 2. 反射创建对象
Class<?> clazz = Class.forName(classPath);
return (Demo) clazz.newInstance();
}
}
3.3 IOC 容器两大实现类
Spring IOC 容器管理的对象统称为 Bean,容器有两个核心接口:
- BeanFactory
- Spring 底层原生接口,框架内部使用,不推荐开发者直接使用;
- 加载策略:懒加载 ,加载配置文件时不创建对象,调用
getBean()时才实例化。
- ApplicationContext
BeanFactory的子接口,功能更强大,开发首选;- 加载策略:立即加载,容器初始化时就创建所有单例 Bean;
- 额外拓展:支持国际化、事件发布等功能。
第四章 Bean 的作用域
通过 <bean> 标签的 scope 属性配置 Bean 作用域,Spring 5 共提供 6 种,常用两种:
-
singleton(默认)
-
单例作用域:整个 IOC 容器中仅存在一个 Bean 实例;
-
容器初始化时创建对象,全局共享。
<bean id="demo" class="com.qcby.service.Demo" scope="singleton"/>
-
-
prototype
-
多例作用域:每次调用
getBean()都会创建全新对象; -
容器启动时不创建对象,获取时才实例化。
<bean id="demo" class="com.qcby.service.Demo" scope="prototype"/>
-
第五章 Spring Bean 管理
5.1 Bean 管理概念
Bean 管理包含两大核心操作:
- 创建类的实例对象;
- 为对象的成员属性依赖注入(DI)。
5.2 Bean 管理两种方式
- 基于 XML 配置文件(传统方式);
- 基于 注解(主流开发方式)。
5.3 基于 XML 的 Bean 管理
5.3.1 XML 创建对象
默认通过无参构造方法实例化,类必须提供无参构造,否则容器创建失败。
<bean id="demo" class="com.qcby.service.Demo"/>
5.3.2 XML 依赖注入(DI)
DI(Dependency Injection)依赖注入:Spring 自动为对象属性赋值,分为 Set 注入 、构造器注入。
1)Set 方式注入(最常用)
要求:属性必须提供 setXxx() 方法。
① 普通属性 + 对象属性注入
实体类:
package com.qcby.service;
public class User {
private int age;
private String name;
private Demo demo; // 引用类型
// 必须提供set方法
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setDemo(Demo demo) {
this.demo = demo;
}
@Override
public String toString() {
return "User{age=" + age + ", name='" + name + "', demo=" + demo + "}";
}
}
XML 配置:
-
value:给基本类型 / 字符串赋值; -
<bean id="demo" class="com.qcby.service.Demo"/> <bean id="user" class="com.qcby.service.User" > <property name="age" value="18"/> <property name="name" value="张三"/> <property name="demo" ref="demo"/> </bean>ref:引用容器中其他 Bean 的 id。
测试代码:
@Test
public void testUser(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = ac.getBean("user", User.class);
System.out.println(user);
}
② 数组、List、Map 集合注入
实体类:
import java.util.List;
import java.util.Map;
public class CollectionBean {
private String[] strs;
private List<String> list;
private Map<String,String> map;
public void setStrs(String[] strs) { this.strs = strs; }
public void setList(List<String> list) { this.list = list; }
public void setMap(Map<String, String> map) { this.map = map; }
@Override
public String toString() {
return "CollectionBean{strs=" + java.util.Arrays.toString(strs) +
", list=" + list + ", map=" + map + "}";
}
}
XML 配置:
<bean id="collectionBean" class="com.qcby.service.CollectionBean">
<!-- 数组 -->
<property name="strs">
<array>
<value>美美</value>
<value>小凤</value>
</array>
</property>
<!-- List集合 -->
<property name="list">
<list>
<value>熊大</value>
<value>熊二</value>
</list>
</property>
<!-- Map集合 -->
<property name="map">
<map>
<entry key="aaa" value="老王"/>
<entry key="bbb" value="小王"/>
</map>
</property>
</bean>
2)构造器方式注入
要求:类提供有参构造方法 ,使用 <constructor-arg> 标签赋值。 实体类:
public class Car {
private String cname;
private Double money;
// 有参构造
public Car(String cname,Double money){
this.cname = cname;
this.money = money;
}
@Override
public String toString() {
return "Car{cname='" + cname + "', money=" + money + "}";
}
}
XML 配置:
<bean id="car" class="com.qcby.service.Car">
<constructor-arg name="cname" value="奔驰"/>
<constructor-arg name="money" value="35"/>
</bean>
5.4 基于注解的 Bean 管理
注解作用:简化 XML 配置,是现代开发主流方式。
5.4.1 实例化 Bean 四大注解
四个注解功能完全一致,仅用于分层区分:
@Component:通用普通组件;@Controller:标注控制层类;@Service:标注业务层类;@Repository:标注数据访问层类。
规则:不指定名称时,Bean id 默认是类名首字母小写 ;可通过
@注解名(value="自定义id")指定名称。
5.4.2 注解开发步骤
-
业务类添加注解
package com.qcby.testanno;
import org.springframework.stereotype.Controller;
@Controller(value="us")
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("使用注解,方便吧!");
}
} -
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:context="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 http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.qcby"/>
</beans> -
测试获取 Bean
@Test
public void run1(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService us = (UserService) ac.getBean("us");
us.hello();
}
5.4.3 注解实现属性注入
@Value:注入普通类型、字符串;@Autowired:按类型自动装配(引用类型);@Qualifier:配合@Autowired,按名称装配,不可单独使用;@Resource:JDK 原生注解,默认按名称注入。
示例代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component(value = "c")
public class Car {
@Value("大奔2")
private String cname;
@Value("400000")
private Double money;
// 按类型注入
@Autowired
// 按名称注入(搭配使用)
// @Qualifier(value = "person")
// JDK注解 按名称注入
// @Resource(name = "person")
private Person person;
@Override
public String toString() {
return "Car{cname='" + cname + "', money=" + money + ", person=" + person + "}";
}
}
@Component
class Person {
@Value("张三")
private String pname;
@Override
public String toString() {
return "Person{pname='" + pname + "'}";
}
}
5.5 纯注解开发(无 XML)
微服务主流方案,使用配置类完全替代 XML 文件。
核心注解
@Configuration:标识当前类为 Spring 配置类;@ComponentScan:开启包扫描。
实现步骤
-
实体类添加组件注解
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class Order {
@Value("北京")
private String address;@Override public String toString() { return "Order{address='" + address + "'}"; }}
-
编写 Spring 配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration // 声明配置类
@ComponentScan(value = "com.qcby") // 包扫描
public class SpringConfig {
} -
测试(使用
AnnotationConfigApplicationContext加载配置类)import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Demo4 {
@Test
public void run(){
// 加载配置类,初始化容器
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
Order order = (Order) ac.getBean("order");
System.out.println(order);
}
}
第六章 Bean 的生命周期
6.1 完整生命周期 8 大阶段
- 实例化 :IOC 容器通过无参构造创建 Bean 对象;
- 属性注入 :调用
set方法完成属性赋值; - 初始化前置处理 :Bean 后置处理器
postProcessBeforeInitialization; - 初始化:执行自定义初始化方法;
- 初始化后置处理 :Bean 后置处理器
postProcessAfterInitialization; - 就绪可用:Bean 正式交付业务使用;
- 销毁:容器关闭时,执行自定义销毁方法;
- 容器关闭。
6.2 生命周期回调三种方式
用于指定 Bean 初始化、销毁时执行的方法,优先级:注解 > 接口 > XML。
方式 1:实现接口(耦合度高,不推荐)
实现 InitializingBean(初始化)、DisposableBean(销毁)接口:
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Dog implements InitializingBean, DisposableBean {
private String name;
public Dog() {
System.out.println("Dog 对象被创建");
}
public void setName(String name) {
this.name = name;
}
// 初始化方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("接口初始化方法执行");
}
// 销毁方法
@Override
public void destroy() throws Exception {
System.out.println("接口销毁方法执行");
}
}
方式 2:XML 配置指定方法
在 <bean> 标签中配置 init-method(初始化)、destroy-method(销毁):
<bean id="dog" class="com.qcby.Dog"
init-method="init"
destroy-method="destroyFun"/>
方式 3:注解方式(推荐)
使用 @PostConstruct(初始化)、@PreDestroy(销毁)。
6.3 Bean 后置处理器
- 作用:对容器中所有 Bean 生效,在初始化前后统一拦截处理;
- 实现
BeanPostProcessor接口。
示例:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanProcessor implements BeanPostProcessor {
// 初始化之前执行
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化前:" + beanName);
return bean;
}
// 初始化之后执行
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化后:" + beanName);
return bean;
}
}
XML 配置:将后置处理器交由容器管理即可全局生效
<bean id="myBeanProcessor" class="com.gs.process.MyBeanProcessor"/>
补充依赖(Lombok)
项目常用简化代码工具,Maven 依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>