spring从入门到精通(spring学习笔记,持续更新中)
一.什么是spring?
Spring是分层的 Java SE/EE应用 full-stack(全栈式) 轻量级开源框架。它的主要目标是让 Java 企业级应用开发变得更加容易,提供了一种综合的编程和配置模型。
提供了表现层 SpringMVC和持久层 Spring JDBC Template以及 业务层 事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。
举个例子:
你可以把 Spring 想象成一个超级工厂和一个智能管家。
在传统的程序开发中,如果你想用到一个对象(比如一个 UserService
对象),你需要自己亲手去 new
一个:
UserService userService = new UserService();
这就像你想用一个玩具,需要自己去买零件、自己组装。当玩具很多、很复杂时,管理起来会非常麻烦。
而 Spring 这个“超级工厂”接管了所有对象的创建工作。你只需要告诉工厂:“我需要一个 UserService
”,工厂就会自动制造好(或找到)一个给你。你不需要关心它是怎么做的。
同时,Spring 也是一个“智能管家”。它不仅创建对象,还会自动帮你把对象之间的依赖关系处理好。比如,你的 UserService
需要依赖一个 UserMapper
(用来访问数据库),管家会自动把创建好的 UserMapper
“注入”到 UserService
里面去。这个过程就是 控制反转(IoC) 和 依赖注入(DI),它是 Spring 框架最核心的基础。
综上所述:Spring 是一个通过控制反转和依赖注入来管理对象生命周期和关系,并提供了AOP、数据访问、Web开发等一系列强大功能的综合性企业级应用开发框架。
二.spring的核心思想特性以及体系结构
1.核心思想
(1)控制反转(IoC)
传统开发(正转):程序员在代码中主动创建 (
new
) 和管理对象及其依赖关系。就像你自己动手造零件、组装汽车。Spring(反转):将创建和管理对象的控制权反转给了 Spring 容器。你只需要“告诉”容器你需要什么(通过配置或注解),容器就会主动创建好对象,并将它依赖的其他对象“注入”给它。就像你把汽车设计图交给工厂,工厂自动为你生产并组装好整辆车。(实现方式:依赖注入)
目的:解耦。让程序组件之间不直接依赖,而是依赖于抽象,使得代码更灵活、更易于测试和维护。
(2)面向切面编程(AOP)
核心问题:在业务系统中,有很多横跨多个模块的通用功能(如日志、事务、安全校验)。如果把这些代码直接写在业务逻辑里,会导致代码冗余和混乱。
AOP 解决方案:将这些横切关注点(通用功能)与核心业务逻辑分离,独立成一个“切面”。然后,在程序运行的合适时机,Spring 会像“插拔”一样,自动将这些切面功能织入到核心业务代码中。
目的:让开发者能专注于核心业务,提高代码的模块化和可维护性。
二.IOC容器
* 传统方式
之前我们需要一个userDao实例,需要开发者自己手动创建 new UserDao();
* IOC方式
现在我们需要一个userDao实例,直接从spring的IOC容器获得,对象的创建权交给了spring控制
示例:实现service层与dao层代码解耦合
目录:

这三段配置合起来,就是告诉项目:我需要用 dom4j 处理 XML,用 jaxen 辅助查 XML 内容,再用 JUnit 做代码测试







上面的service对象和dao对象耦合度太高,而且每次new的都是一个新的对象,导致服务器压力过大。
优化一下代码:
Beans.xml文件:
BeanFactory工具类
static代码块作用:初始化IOC容器,提前创建所有对象(在类被加载到内存时自动执行,且只执行一次。)就是在程序启动时,完成 “对象的批量创建和存储”。简单来说static块就像 “仓库管理员”,在程序启动时按清(beans.xml)把所有需要的 “工具”(对象)提前造好,统一放进仓库(ioc map)里,后续用的时候直接拿,不用再临时造。
getBean方法的作用:从容器中获取对象是对外提供的 “取对象” 的接口,作用很直接:根据传入的beanId(就是<bean>标签里的id),从ioc map 中取出对应的对象返回。
修改Service接口和实现类
总结:
(一)初始耦合版本:硬编码创建对象(高耦合)
此版本中,对象由业务代码直接
new
创建,模块间依赖强绑定,执行逻辑如下:
test 模块(测试入口)触发执行测试类
UserTest
中的@Test
注解方法testSave()
是执行入口:
第一步:
new UserServiceImpl()
—— 手动创建Service
层实例(UserServiceImpl
);第二步:调用
userService.save()
—— 触发Service
层的业务逻辑。Service 模块调用 Dao 模块
UserServiceImpl
的save()
方法中,通过硬编码创建Dao
层实例:
执行
userDao = new UserDaoImpl()
—— 手动创建Dao
层实例(UserDaoImpl
);调用
userDao.save()
—— 触发Dao
层的数据访问逻辑(输出 “保存成功了...”)。核心问题
调用逻辑依赖 “硬编码”:
Service
直接依赖Dao
的具体实现类(UserDaoImpl
),若Dao
实现类变更(如换UserDaoImpl2
),需修改Service
代码;对象重复创建:每次调用
save()
都会new
新的UserDaoImpl
,增加服务器资源消耗。(二)优化后 IOC 版本:容器管理对象(解耦)
此版本引入
Utils
模块(BeanFactory
)和beans
模块(beans.xml
),将 “对象创建权转移到容器”,执行逻辑分为 “容器初始化” 和 “业务调用” 两阶段:阶段 1:容器初始化(程序启动时自动执行,仅 1 次)
由
Utils
模块的BeanFactory
静态代码块触发,核心是 “读取beans
配置→解析→创建对象→存入容器”:
beans 模块(配置源)提供信息
beans.xml
中通过<bean id="userDao" class="com.hhxy.Dao.impl.UserDaoImpl"/>
定义:
id
:Dao
对象的唯一标识(“userDao”);
class
:Dao
实现类的全路径名(用于后续反射创建对象)。Utils 模块(IOC 容器)执行初始化
BeanFactory
的静态代码块(程序启动时,BeanFactory
类加载即执行):
读配置:通过类加载器获取
beans.xml
输入流;解析 XML:用
dom4j
+jaxen
解析,通过 XPath 表达式//bean
定位所有<bean>
标签;反射创建对象:通过
Class.forName(className).newInstance()
,根据class
属性的全路径名,动态创建UserDaoImpl
实例;存入容器:将 “
id=userDao
→UserDaoImpl
实例” 存入静态Map<String, Object> ioc
(Map
作为 IOC 容器,实现对象复用)。阶段 2:业务调用(测试触发,多次复用对象)
test 模块(入口)触发执行同初始版本,
UserTest.testSave()
先new UserServiceImpl()
(仅创建Service
实例,不创建Dao
实例),再调用userService.save()
。Service 模块调用 Utils 模块获取 Dao 对象
UserServiceImpl
的save()
方法修改为:userDao = (UserDao) BeanFactory.getBean("userDao")
—— 通过Utils
模块的getBean()
方法,从ioc
容器中获取已创建好的UserDaoImpl
实例(无需new
)。Dao 模块执行逻辑调用
userDao.save()
,执行Dao
层数据访问逻辑,输出 “保存成功了...”。