JavaSSM框架从入门到精通!第六天(Spring篇 一)
2026/5/26 3:42:58 网站建设 项目流程

一、Spring 框架概述

1. Spring 框架的作用

Spring 框架的作用就是为了代码的“解耦”,为了降低代码之间的耦合度。根据功能不同,可以将系统中的代码分为主业务逻辑代码交叉业务逻辑代码:

  • 主业务逻辑代码:有具体的专业业务应用场景,复用性比较低。

  • 交叉业务逻辑代码:没有专业业务应用场景,主要是为主业务逻辑提供系统级的服务,例如日志、安全、事务等等,复用性比较强。

2. Spring 框架降低耦合度的方式

Spring 框架降低耦合度的方式分为两种:控制反转 (IoC)面向切面编程 (AOP)

  • IoC:主业务逻辑在相互调用的过程中,不再自己去创建要使用的对象,而是由 Spring 容器统一管理,在主业务逻辑需要的时候,自动“注入”给主业务逻辑。

  • AOP:使得交叉业务逻辑得到最大的复用,且交叉业务逻辑不会混杂在主业务逻辑中,而是由 Spring 容器统一完成”织入“。

3. Spring 的体系结构

Spring 由 20 多个模块组成,它们可以分为:数据访问/集成 (Data Access/Integration)、Web、面向切面编程 (AOP、Aspect)、用于服务器设备管理 (Instrumentation)、消息发送 (Messaging)、核心容器 (Core Container) 和 测试 (Test)。

4. Spring 的下载

Spring 官网:http://spring.io

5. Spring 的特点

  • (1) 非侵入式:Spring 框架的 API 不会出现在主业务逻辑代码中,即主业务逻辑代码是一个普通的 Java 类 (pojo),可以快速移植到其他框架。

  • (2) 容器:Spring 作为一个容器,可以管理对象的生命周期、对象与对象之间的依赖关系,可以通过配置文件来定义对象以及设置对象与对象之间的关系。

  • (3) IoC (控制反转):创建被调用的实例不是由调用者完成,而是由 Spring 容器完成,然后注入给调用者。这样就降低了主调方和被调方的耦合度。

举个例子:

// 传统的做法
main(){
// 主调方法 main() 和被调方 Student 对象耦合在一起了
Student student = new Student();
student.show();
}

// Spring 的 IoC:将 student 对象配置到 Spring 容器中
main() {
// 从 Spring 容器中获取 student 对象,降低了代码之间耦合度
student.show();
}

(4) AOP (面向切面编程):是一个编程思想,是对面向对象编程的补充。通过分离主业务逻辑和交叉业务逻辑,将复用性比较高的日志、安全、事务等单独写在一个称为“切面”的类中。在需要时将”切面“动态的“织入”到主业务逻辑中,降低代码的耦合性。

二、Spring 与 IoC

1. IoC 实现方式

IoC 是一个概念,也是一种思想,其实现方式有多个,目前比较流行的:

  • (1) 依赖查找 (DL, Dependency Lookup):容器提供回调接口和上下文环境给组件,程序代码则需要提供具体的查找方式。典型的应用就是 JNDI 系统查找(应用不多)。

  • (2) 依赖注入 (DI, Dependency Injection):程序代码不做定位查询,由外部容器自己完成。依赖注入是目前最优秀的解耦方式。

2. 开发第一个 Spring 应用 (DI 的体现)

(1) 导入 Spring 的基础 jar 包

包含 beans、core、context、expression 以及依赖库 commons-logging,还可以引入 log4j 日志包和 junit 测试包。

(2) 定义主业务逻辑接口和实现类

接口:

package com.edu.service; public interface IStudentService { void show(); }

实现类:

package com.edu.service.impl; import com.edu.service.IStudentService; public class StudentServiceImpl implements IStudentService { @Override public void show() { System.out.println("我是一个学生"); } }
(3) 创建 Spring 的主配置文件

srcresources目录下创建applicationContext.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"> <bean id="studentService" class="com.edu.service.impl.StudentServiceImpl"/> </beans>
(4) 测试类
package com.edu.test; import com.edu.service.IStudentService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MySpringTest { @Test public void testFirstSpringApp(){ // 1. 读取 Spring 的主配置文件,获取 Spring 的容器:ApplicationContext ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 2. 从容器中获取 bean 对象 IStudentService studentService = context.getBean("studentService", IStudentService.class); studentService.show(); } }

3. ApplicationContext 容器

ApplicationContext用于加载核心配置文件,充当“容器”的角色,其常用实现类有:

  1. ClassPathXmlApplicationContext:配置文件在类路径下 (srcresources目录)。

  2. FileSystemXmlApplicationContext:配置文件在本地磁盘目录中或项目的根路径下。

4. BeanFactory 接口容器

BeanFactoryApplicationContext的父接口,也可以作为 Spring 容器,其实现类有XmlBeanFactory。需要将配置文件以Resource形式传递:

@Test public void testBeanFactory(){ BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml")); IStudentService studentService = factory.getBean("studentService", IStudentService.class); studentService.show(); }

ApplicationContext 和 BeanFactory 的区别:

  • ApplicationContext:容器创建时就已经将对象装配好。执行效率高,比较占内存(空间换时间)。

  • BeanFactory:采用延迟装配策略,第一次调用getBean()时才去装配对象。节约内存,响应速度慢(时间换空间)。

  • 注意:Spring 容器在装配 bean 对象时默认调用无参构造方法。

5. Bean 的装配

(1) 默认装配方式

调用 bean 的无参构造器创建空值对象。

(2) 动态工厂 Bean

利用 Spring 提供的factory-beanfactory-method属性:

<bean id="factory" class="com.edu.utils.ServiceFactory"/> <bean id="studentService" factory-bean="factory" factory-method="getStudentService"/>
(3) 静态工厂 bean

无需工厂实例,直接通过工厂类的静态方法创建:

<bean id="studentService" class="com.edu.utils.ServiceFactory" factory-method="getStudentService"/>
(4) 容器中 bean 的作用域 (scope)
作用域说明
singleton默认值。单例模式,整个容器中只有一个实例。(非线程安全)
prototype原型模式。每次getBean()都会创建一个新的实例。(延迟加载,线程安全)
requestWeb 应用中,每次 HTTP 请求产生一个不同的 bean 对象。
sessionWeb 应用中,每次 HTTP 会话产生一个不同的 bean 对象。
global sessionWeb 集群应用中,全局 HTTP 会话对应一个 bean 对象。
(5) Bean 后处理器 (BeanPostProcessor)

是一个特殊的 bean,容器初始化 bean 时自动执行该类的前置和后置方法,常用于结合 JDK 动态代理对目标 bean 进行增强。

(6) 定制 bean 的生命周期

通过init-methoddestroy-method属性指定初始化和销毁方法:

<bean id="someService" class="com.edu.service.impl.SomeServiceImpl" init-method="setUp" destroy-method="tearDown"/>

三、基于 XML 配置的 DI(依赖注入)

1. 设值注入 (setter 注入)

要求 bean 必须有默认构造方法和对应属性的 setter 方法。

  • 基本类型注入:使用<property name="..." value="..."/>

  • 域属性注入 (对象引用):使用<property name="..." ref="..."/>

<bean id="school" class="com.edu.beans.School"> <property name="id" value="10011"/> <property name="name" value="清华大学"/> </bean> <bean id="student" class="com.edu.beans.Student"> <property name="id" value="11011"/> <property name="name" value="小明"/> <property name="school" ref="school"/> </bean>

2. 构造注入

要求 bean 必须有全参构造函数。

<bean id="student" class="com.edu.beans.Student"> <constructor-arg name="id" value="100011"/> <constructor-arg name="name" value="娜娜"/> <constructor-arg name="school" ref="school"/> </bean>

3. 集合属性的注入

支持数组<array>、List<list>、Set<set>、Map<map>和 Properties<props>的注入。

<property name="students"> <list> <ref bean="student1"/> <ref bean="student2"/> </list> </property>

4. 对域属性的自动注入 (autowire)

  • byName:根据域属性的名称和 Spring 容器中 bean 的 id 匹配注入。

  • byType:根据类型同源(相同类型或其子类/实现类)自动匹配注入。注意容器中同源的 bean 只能有一个。

5. 使用 SPEL 注入

Spring EL 表达式,语法#{...}

<property name="personAge" value="#{T(java.lang.Math).random()*30}"/> <property name="empName" value="#{person.personName.toString()}"/>

6. 使用抽象 bean 注入

使用abstract="true"标记父 bean,子 bean 使用parent="父bean的id"继承属性,减少冗余配置。

7. 多配置文件加载

可以使用<import resource="spring-*.xml"/>在总配置文件中引入其他子配置文件。

四、基于注解的 DI (依赖注入)

开启注解扫描 (需引入 AOP 包):

<context:component-scan base-package="com.edu.beans"></context:component-scan>

1. 常用创建对象的注解

  • @Component:通用组件注解。

  • @Repository:用于 Dao 层。

  • @Service:用于 Service 层。

  • @Controller:用于 Web 控制层。

2. 属性注入注解

  • @Value:注入基本数据类型。

  • @Autowired:按类型自动注入域属性。

  • @Qualifier("beanId"):配合@Autowired实现按名称注入。

  • @Resource:默认按类型注入,@Resource(name="beanId")按名称注入。

3. 其他相关注解

  • @Scope("prototype"):设置作用域。

  • @PostConstruct:初始化方法。

  • @PreDestroy:销毁方法。

4. JavaConfig 配置类

使用@Configuration标注配置类,@Bean标注向容器注册对象的方法。

@Configuration public class DataSourceConfig { @Bean(name = "dataSource") public DataSource dataSource(){ return new DataSource("com.edu.jdbc.Driver","jdbc:mysql://localhost:3306/test","root","root"); } }

5. Spring Test 整合 JUnit

@RunWith(SpringRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class SpringTest { @Autowired private IUserService userService; // ... @Test methods }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询