Spring 依赖注入、AOP代理全方面解析

 更新时间:2025年08月11日 11:16:21   作者:Arva .  
文章介绍了软件开发中的开闭原则、依赖倒置原则及Spring非侵入式设计,通过IoC和DI实现解耦,提升系统扩展性、可测试性及架构迁移能力,强调框架能力以无感知方式注入业务代码的核心优势,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧

OCP

O代表Open ,C代表Closed
在软件开发过程中应当对扩展开放,对修改关闭。也就是说,如果在进行功能扩展的时候,添加额外的类是没问题的,但因为功能扩展而修改之前运行正常的程序,这是忌讳的,不被允许的。因为一旦修改之前运行正常的程序,就会导致项目整体要进行全方位的重新测试。

DIP

依赖倒置原则(Dependence Inversion Principle),简称DIP,主要倡导面向抽象编程,面向接口编程,不要面向具体编程,
让上层不再依赖下层,下面改动了,上面的代码不会受到牵连。
怎么做到呢?当然是用接口。
这样可以大大降低程序的耦合度,耦合度低了,扩展力就强了,同时代码复用性也会增强。(软件七大开发原则都是在为解耦合服务)

控制反转IoC(Invension of Control)
控制反转是一种新型的设计模式
交出的权力
new对象的权力
对象之间的关系(到底用的是哪一个实现类)

Spring

是实现类IoC的容器。
IOC是思想,DI是实现。通过DI实现bean管理(有bean对象的创建和bean与bean之间关系的维护)。
DI(依赖注入)有set注入和构造注入

依赖注入之set注入

这里最后一行的理解,先能找到是哪一个set方法,再找到形参对应的实际参数到底在哪里。

外部 Bean

  • 在 Spring 配置文件中单独定义
  • 可以被多个其他 Bean 引用
  • 有自己独立的 ID/名称
<!-- 外部 Bean 定义 -->
<bean id="address" class="com.example.Address">
    <property name="city" value="Beijing"/>
</bean>
<!-- 引用外部 Bean -->
<bean id="employee" class="com.example.Employee">
    <property name="address" ref="address"/>
</bean>

内部 Bean

  • 直接在引用它的 Bean 内部定义
  • 只能被当前 Bean 使用
  • 没有独立的 ID/名称
<bean id="employee" class="com.example.Employee">
    <property name="address">
        <!-- 内部 Bean 定义 -->
        <bean class="com.example.Address">
            <property name="city" value="Beijing"/>
        </bean>
    </property>
</bean>

作用范围不同

特性外部 Bean内部 Bean
作用域全局可用仅限当前 Bean 内部使用
生命周期由容器管理随外部 Bean 创建和销毁
是否可重用是,可被多个 Bean 引用否,只能被当前 Bean 使用

构造注入

set注入在创建对象之后,而构造注入在创建对象的时候就注入了。
xml解析+工厂模式+反射机制
IoC思想的一种具体实现是依赖注入DI
八大框架

两个核心模块 IoC AOP
AOP
ORM(Object-Relational Mapping,对象关系映射) 是一种编程技术,用于在 面向对象编程语言(如 Java、Python)中的对象与 关系型数据库(如 MySQL、PostgreSQL)的表之间建立映射关系,从而让开发者能够以操作对象的方式间接操作数据库,无需直接编写复杂的 SQL 语句。

Spring的非侵入体现在哪里

Spring框架的非侵入式(Non-Invasive)设计是其核心哲学之一,指的是它不会强制要求你的代码必须依赖Spring特定的类或接口,而是允许你以原生方式编写业务逻辑,仅在需要时通过配置或注解引入Spring的能力。以下是具体分析:

1. 什么是“非侵入式”?

传统框架的侵入性
例如早期的EJB 2.x,要求业务类必须继承特定父类或实现指定接口(如SessionBean),代码与框架深度耦合。

// EJB 2.x的侵入式写法(必须实现框架接口)
public class UserService implements SessionBean {
    // 必须实现框架方法
    public void ejbActivate() {} 
    // 业务逻辑...
}

Spring的非侵入性
你的类可以是纯POJO(Plain Old Java Object),无需继承或实现Spring的类/接口。

// Spring中的POJO(完全独立于框架)
public class UserService {
    public void addUser(String name) { 
        // 纯业务逻辑
    }
}

2. Spring如何实现非侵入式?

(1)依赖注入(DI)通过配置/注解实现

不需要实现特定接口,只需通过@Autowired或XML配置即可注入依赖:

@Service
public class OrderService {
    @Autowired  // 通过注解注入,不依赖Spring接口
    private PaymentService paymentService;
}
(2)AOP通过代理模式实现

切面编程通过动态代理(JDK/CGLIB)增强功能,业务类无需感知:

@Transactional  // 只需添加注解,不改变类继承结构
public void updateOrder(Order order) {
    // 业务代码
}
(3)模板模式消除样板代码

JdbcTemplate封装了JDBC的繁琐操作,但你的DAO类无需继承任何Spring类:

@Repository
public class UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate; // 直接使用,无需实现Spring接口
}

3. 非侵入式的核心优势

特性侵入式框架Spring(非侵入式)
代码耦合度高(依赖框架父类/接口)低(POJO + 配置/注解)
可测试性需依赖框架环境测试可直接单元测试(无框架依赖)
迁移成本重构代价高轻松切换其他框架或去Spring化
灵活性受框架设计限制自由选择技术组合

4. 对比其他框架

  • 侵入式框架示例

    • Struts 1.x(Action需继承ActionForm
    • EJB 2.x(需实现SessionBean
  • Spring的非侵入式体现

    • 你的UserService可以同时用于Spring、非Spring环境,甚至移植到Quarkus/Micronaut。
    • 仅需修改配置(如从XML换为@Bean),无需改动业务代码。

总结

Spring通过依赖注入、AOP代理、模板模式等设计,将框架能力以无感知方式注入到业务代码中,使得开发者可以:
✅ 用原生Java对象编写核心逻辑
✅ 按需选择Spring功能(而非强制)
✅ 轻松迁移或与其他框架集成

这种设计正是Spring能成为Java生态基石的关键原因之一。

到此这篇关于Spring 依赖注入、AOP代理全方面解析的文章就介绍到这了,更多相关Spring 依赖注入AOP内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • jsp+dao+bean+servlet(MVC模式)实现简单用户登录和注册页面

    jsp+dao+bean+servlet(MVC模式)实现简单用户登录和注册页面

    这篇文章主要介绍了jsp+dao+bean+servlet(MVC模式)实现简单用户登录和注册页面,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 基于Spring实现搜索目录下指定名称文件

    基于Spring实现搜索目录下指定名称文件

    这篇文章主要为大家详细介绍了如何基于Spring实现搜索目录下指定名称文件,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-08-08
  • Spring Task定时任务的完整使用教学

    Spring Task定时任务的完整使用教学

    Spring Task是Spring框架提供的轻量级定时任务工具,它无需依赖额外的第三方库,直接集成在Spring核心包中,在SpringBoot中,Spring Task提供了自动配置支持,只需少量注解即可快速实现定时任务功能,本文给大家介绍了Spring Task定时任务的完整使用教学
    2026-06-06
  • 浅谈Spring自定义注解从入门到精通

    浅谈Spring自定义注解从入门到精通

    这篇文章主要介绍了浅谈Spring自定义注解从入门到精通,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • SpringMVC中的ConversionServiceExposingInterceptor工具类解析

    SpringMVC中的ConversionServiceExposingInterceptor工具类解析

    这篇文章主要介绍了SpringMVC中的ConversionServiceExposingInterceptor工具类解析,ConversionServiceExposingInterceptor是Spring MVC的一个HandlerInterceptor,用于向请求添加一个属性,需要的朋友可以参考下
    2023-12-12
  • Java 利用递归实现链表的归并排序

    Java 利用递归实现链表的归并排序

    这篇文章主要介绍了Java 如何利用递归实现链表的归并排序,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-09-09
  • Springboot第三方jar打不进jar里的问题分析及解决

    Springboot第三方jar打不进jar里的问题分析及解决

    文章介绍了如何解决在Maven项目中无法从maven仓库找到的第三方jar包问题,通过将这些jar包添加到本地库,使用特定的命令设置groupId、artifactId、版本号、包类型和文件路径,此方法适用于在Windows环境下的操作,并需要安装Maven环境变量
    2025-10-10
  • 浅谈java泛型的作用及其基本概念

    浅谈java泛型的作用及其基本概念

    下面小编就为大家带来一篇浅谈java泛型的作用及其基本概念。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • springBoot之如何获取接口请求数据和返回数据实现日志

    springBoot之如何获取接口请求数据和返回数据实现日志

    这篇文章主要介绍了springBoot之如何获取接口请求数据和返回数据实现日志问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • springboot实现对注解的切面案例

    springboot实现对注解的切面案例

    这篇文章主要介绍了springboot实现对注解的切面过程,首先定义一个注解、再编写对注解的切面只是记录的执行时间和打印方法,可以实现其他逻辑,需要的朋友可以参考一下
    2022-01-01

最新评论