尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Spring的基础概念

Spring的基础概念 深度解读“注入”从生活隐喻到软件开发中的控制反转在学习和使用 Spring 框架时“依赖注入Dependency Injection简称 DI”是绕不开的核心概念。很多初学者会将其字面理解为“把依赖添加进去”甚至与 Maven/Gradle 中添加 Jar 包混淆。本文将带你跨越这一认知鸿沟从抽象概念、生活对比到代码实战彻底理解“注入”在软件开发中的真正含义。一、怎么理解“注入”这一抽象概念1.1 核心定义在软件工程中“注入Injection”指的是将一个对象或数据由外部主动传递给另一个对象而不是由接收对象自己去创建或查找该对象。这一行为包含三个关键要素被动接收者目标对象如UserService只负责“伸手接住”传进来的东西不负责“生产”它。主动授予者外部调用者通常是 Spring IoC 容器负责“推”送依赖对象。传递介质通过构造器参数、Setter 方法参数或字段赋值。1.2 与传统方式的本质区别传统方式主动查找UserService需要UserDao于是自己new UserDaoImpl()。这好比你需要吃饭得自己去地里种菜、买菜、做饭。依赖注入被动接收UserService只需要声明“我需要UserDao”Spring 容器就把现成的UserDao对象通过构造器或 Setter 方法“塞”给它。这好比你去餐厅往椅子上一坐服务员把做好的菜端到你面前。哲学本质“注入”是实现控制反转IoC的手段。控制权从对象内部自己创建依赖反转给了外部容器容器创建并传递依赖。二、他和生活中的“注入”有什么区别日常生活中我们常见的“注入”是医学上的“打针”或工业上的“注水”。计算机科学借用了这一词汇但含义大相径庭维度生活中的注入物理软件中的注入逻辑操作对象液体、气体、药物有物理体积和形态。内存中的对象引用一段内存地址。传输方式通过针头、管道施加物理压力强制推进。通过赋值语句、函数参数传递无物理压力。作用结果物质混合或填充空间改变物理成分。目标对象获得依赖对象的引用从而能调用其方法。方向性通常是单向、不可逆的物理推进。是双向的逻辑连接目标对象持有引用即可随时调用。总结生活“注入”是物质迁移软件“注入”是内存引用拷贝。它们最大的共同点是**“外部主动给予”**这是借用该词的精髓。三、依赖注入DI是指“添加依赖”吗这是一个极易混淆的概念答案很明确不是3.1 “添加依赖” vs “注入依赖”添加依赖Adding Dependency指在项目构建文件如pom.xml或build.gradle中引入第三方 Jar 包。这是编译时或构建时的行为解决的是“这个库是否存在”的问题。依赖注入Dependency Injection指在程序运行时将一个已经存在于内存中的 Bean 对象赋值给另一个对象的属性。解决的是“我这个对象要用到的那个具体实例从哪里来”的问题。3.2 打个比方添加依赖相当于你注册了美团外卖的账号下载了 APP引入库。依赖注入相当于你在 APP 上下单外卖小哥把饭菜送到你手上外部将对象传入。核心记忆点添加依赖是准备材料依赖注入是把材料送到手中。四、代码中的“注入”长什么样看下面这个经典例子感受“被动接收”的精髓// 1. 定义 Dao 组件由容器管理RepositorypublicclassUserDao{publicvoidsave(){/*...*/}}// 2. 定义 Service 组件ServicepublicclassUserService{// 注入点声明需要但不自己创建privatefinalUserDaouserDao;// 构造器注入Spring 容器在实例化 UserService 时// 会主动把容器中已经存在的 UserDao 对象作为参数传递进来。AutowiredpublicUserService(UserDaouserDao){this.userDaouserDao;// 这就是“注入”发生的时刻}}这个过程中UserService没有写UserDao dao new UserDao()。Spring 容器在启动时先创建了UserDao的实例然后在创建UserService时强行把UserDao的引用传进了构造器。你可以这样理解就像 Spring 容器拿着一个针管构造器把UserDao这个对象“推进”了UserService的内存空间中。五、为什么非要“注入”而不用“自己创建”解耦少改代码如果UserService自己new UserDao()那么UserService就死死绑定了UserDao的具体实现。如果后续换成UserDaoV2就必须修改UserService源码。使用注入后只需改配置业务代码不动符合开闭原则。便于测试Mock单元测试时我们不需要真实的数据库连接。通过注入我们可以注入一个假的UserDaoMock 对象进UserService从而隔离测试。单例复用容器管理对象后UserDao可能在整个应用中只存在一个实例单例注入能让所有 Service 共用这一个实例节省内存。六、总结一张图读懂“注入”抽象概念生活中的类比软件中的实现依赖Dependency你需要的那道菜鱼香肉丝。UserService需要的UserDao。获取依赖Get你自己下厨房炒菜new。主动调用context.getBean(UserDao.class)。注入依赖Inject你坐在餐厅里等服务员端上来。容器通过Autowired把对象赋值给类属性。容器Container餐厅的后厨和管理系统。Spring IoC 容器ApplicationContext。最终解释“注入”是一种“被动接收外部资源”的编程思想是区别于传统硬编码创建的高级解耦模式。它不表示添加新文件或新库而是表示由容器在运行时为对象填充其所需的外部资源另一个对象。理解这一点你就真正理解了 Spring 的灵魂。Bean和对象在 Spring 框架的学习过程中许多开发者都会遇到一个本质性的困惑Spring Bean 和 Java 对象到底有什么关系为什么 Spring 要引入“Bean”这个概念而不是直接使用面向对象OOP中的对象面向对象的知识是不是理解 Spring 的前提本文将从 OOP 基础出发结合 Spring 的依赖注入DI和控制反转IoC深入剖析 Bean、对象与注解之间的内在联系帮助读者构建完整的知识体系。一、从 OOP 对象到 Spring Bean概念演进1.1 什么是 Java 对象在面向对象编程OOP中对象是类的实例是内存中存储数据和行为的实体。OOP 的核心思想包括封装将数据和行为打包在一起隐藏内部细节。继承子类复用父类特性建立层次关系。多态同一接口不同实现提升代码灵活性。OOP 中的对象通过new关键字手动创建其生命周期由 JVM 的垃圾回收GC管理开发者需要自行维护对象之间的依赖关系。1.2 什么是 Spring BeanSpring Bean是由 Spring IoC 容器管理的对象实例。它与普通 Java 对象的本质区别在于管理方式创建由容器通过反射机制创建而非new。生命周期容器管理完整的生命周期实例化 → 属性注入 → 初始化 → 使用 → 销毁。依赖通过依赖注入DI自动装配无需硬编码。增强可被 AOP 代理支持事务、日志等横切逻辑。核心观点Spring Bean 在内存层面就是 Java 对象但在管理层面它是由容器托管的“增强版”对象。二、Bean 与 OOP 对象的区别与联系维度普通 Java 对象Spring Bean创建方式开发者手动new容器自动创建生命周期JVM GC 管理容器管理初始化、销毁回调依赖管理硬编码或手动查找自动注入DI作用域无固定作用域singleton、prototype、request、session 等可扩展性无内置增强机制支持 AOP 代理事务、安全、日志联系Spring Bean 必须基于 OOP 类定义它依赖 OOP 的封装、继承和多态特性。接口注入多态是依赖注入的常见形式父子 Bean 关系体现了继承的应用。本质Spring 容器是 OOP 的“装配工”它将分散的类组织成一个可运行的生态系统而 Bean 就是这个生态系统中的活体细胞。三、面向对象是理解 Spring 的基础吗答案是的而且是必修基础。3.1 OOP 为 Spring 提供了理论支撑依赖注入的本质是多态Autowired private UserService userService;注入的是接口依赖运行时多态性选择具体实现。AOP 的底层是代理模式动态代理JDK Proxy / CGLIB是 OOP 设计模式的延伸。容器配置体现组合原则Component标记的类是高内聚、模块化组件的物理表示。3.2 Spring 对 OOP 的补充Spring 并非否定 OOP而是解决了 OOP 在企业级开发中的两大痛点解耦DI 替代了硬编码依赖使代码更易测试和维护。横切关注点AOP 将日志、事务等全局逻辑抽离避免代码散落。学习路径Java 语法OOP→ 设计模式 → Spring 容器基于 OOP 的实现。四、数据可以是对象吗—— 业务数据 vs 配置数据4.1 业务数据Entity / DTO它们通常是 POJO携带业务状态如User、Order。通常不作为 Spring Bean 托管无状态 Bean 更适合容器管理。原因数据对象是无状态的不需要依赖注入更适合作为数据载体而非组件。4.2 配置数据ConfigurationProperties配置数据如数据库 URL、超时时间可通过ConfigurationProperties绑定为配置对象。这些对象可由容器托管便于集中管理和复用。示例ConfigurationProperties(prefixdatasource)ComponentpublicclassDataSourceConfig{privateStringurl;privateStringusername;// getters / setters}结论数据可以是对象但通常只有配置数据适合作为 Spring Bean 托管业务数据对象由程序自行创建。五、注解连接对象与容器的桥梁5.1 注解的角色注解Annotation是 Spring 框架的核心驱动方式之一它通过元数据告诉容器如何创建、装配和管理 Bean。5.2 关键注解解析1Component/Service/Repository标记一个类为 Spring Bean使其被容器扫描并实例化。ServicepublicclassUserService{// 业务逻辑}2Autowired实现依赖注入告诉容器将匹配的 Bean 注入到字段、构造器或方法中。ServicepublicclassOrderService{AutowiredprivateUserServiceuserService;}3Qualifier当存在多个同类型 Bean 时通过名称或限定符精确指定注入哪一个。AutowiredQualifier(oracle)privateDataSourcedataSource;4ConfigurationBean基于 Java 配置的方式显式声明 Bean 创建逻辑。ConfigurationpublicclassAppConfig{BeanpublicDataSourcedataSource(){returnnewHikariDataSource();}}5.3 注解与 OOP 的关系注解是对类的元数据标记不改变类本身的行为。注解让 OOP 中的类能够与 Spring 容器产生关联是“声明式编程”的体现。开发者只需关注业务逻辑OOP 设计容器通过注解完成装配元数据驱动。六、总结Bean、对象、注解三位一体概念角色关联Java 对象内存中的实体OOP 的基本单元Bean 是对象的容器托管版本Spring Bean容器管理的对象支持 DI 和 AOP基于 OOP 类定义通过注解标记注解元数据标记驱动容器行为连接对象与容器实现声明式装配核心观点Spring Bean 是 OOP 对象在容器环境中的延伸它继承了 OOP 的优良设计同时通过容器获得了更强的管理能力。面向对象是学习 Spring 的必修基础不理解多态和接口就无法真正理解依赖注入。注解作为声明式配置的载体使开发者能够专注于 OOP 业务逻辑而将装配细节交给容器处理。理解这些概念之间的关系是掌握 Spring 框架设计哲学的起点也是构建可维护、可扩展企业级应用的基础。
返回列表