Java 新手入门:Spring 两大利器IoC 和 AOP,小白也能轻松理解!

简介: Java 新手入门:Spring 两大利器IoC 和 AOP,小白也能轻松理解!

大家好,今天想跟大家聊聊 Java 开发中两个非常重要的概念:IoC(控制反转) 和 AOP(面向切面编程)。

我知道这两个概念听起来很抽象,但别担心,我会用最通俗易懂的方式,结合生活中的例子,带你一步步揭开它们的神秘面纱!

1、IoC:控制反转,对象的创建交给 Spring 管理!

1.1 传统方式的弊端 - 好比自己动手做蛋糕

想象一下,你要做一个美味的蛋糕。传统的方式是你需要自己去购买面粉、鸡蛋、糖等各种食材,然后按照配方一步步操作,最终才能做出蛋糕。在程序开发中,对象的创建也类似,你需要在代码中使用 new 关键字来创建各种对象,并自己管理它们之间的依赖关系,就像下面这样:

public class Cake {
    private Flour flour;
    private Egg egg;
    private Sugar sugar;
 
    public Cake() {
        this.flour = new Flour();
        this.egg = new Egg();
        this.sugar = new Sugar();
    }
    // ... 其他方法
}

这种方式就像自己一步步做蛋糕,看似简单直接,但随着项目规模的扩大,就会暴露出一些问题:

  • 代码耦合度高: 对象的创建和依赖关系都写死在代码中,就像蛋糕配方写死了,你想换一种面粉都不行,不利于代码的维护和扩展。
  • 测试困难: 如果要替换某个依赖对象,就需要修改大量的代码,就像你想试试不同的鸡蛋,得把整个配方改一遍。
1.2 IoC 横空出世!

为了解决这些问题,IoC 应运而生!IoC 的核心思想是将对象的创建和管理交给 Spring 容器来完成,而不是由开发者自己控制。


就好比做蛋糕,现在你不需要自己动手了,而是直接去蛋糕店订购。你只需要告诉蛋糕店你需要什么口味、尺寸的蛋糕,他们就会帮你准备好所有食材并制作完成,你只需要享受美味即可。

1.3 IoC 实战演练 - 配置你的蛋糕订单

让我们用代码来感受一下 IoC 的魅力吧!

首先,你需要在 Spring 配置文件中定义 Bean,就像告诉蛋糕店你要什么蛋糕:

<bean id="flour" class="com.example.Flour"/>
<bean id="egg" class="com.example.Egg"/>
<bean id="sugar" class="com.example.Sugar"/>
<bean id="cake" class="com.example.Cake">
    <property name="flour" ref="flour"/>
    <property name="egg" ref="egg"/>
    <property name="sugar" ref="sugar"/>
</bean>

然后,你就可以通过 Spring 容器来获取已经做好的蛋糕了:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Cake cake = (Cake) context.getBean("cake");

是不是很简单?通过 IoC,我们不再需要手动创建对象和管理依赖关系,一切都由 Spring 容器帮我们搞定,就像蛋糕店帮你搞定一切一样!

2. AOP:面向切面编程,优雅地处理横切关注点!

2.1 横切关注点

在软件开发中,有些功能是通用的,比如日志记录、性能统计、安全控制等等。这些功能通常被称为“横切关注点”,因为它们会贯穿多个模块。

  • 日志记录: 就像你想记录每个蛋糕的制作时间,用于分析效率。
  • 权限校验: 好比进入蛋糕店的特定区域需要检查权限,确保只有授权的糕点师才能进入。
2.2 传统方式的烦恼 - 到处重复代码?

如果使用传统的方式来处理横切关注点,就需要在每个模块中都添加相同的代码,就像为了记录每个蛋糕的制作时间,你需要在每个糕点师制作蛋糕的代码里都加上记录时间的代码,这会导致代码冗余和维护困难。

2.3 AOP 大显身手!- 高效的切面管理

AOP 的出现就是为了解决这个问题!AOP 允许我们将横切关注点从业务逻辑中分离出来,形成独立的模块,然后通过配置的方式将这些模块织入到目标对象中。


就好比你想记录每个蛋糕的制作时间。AOP 的方式就像是给每个糕点师都配一个计时器,这个计时器会在糕点师开始制作和完成制作时自动记录时间,而糕点师只需要专注于制作蛋糕的流程即可。

2.4 AOP 实战演练 - 自动记录蛋糕制作时间

让我们来看一个具体的例子。假设我们要在每个蛋糕制作方法 execution 前后记录时间,使用 AOP 可以这样做:

// 定义切面,就像定义一个计时器
@Aspect
@Component
public class CakeTimerAspect {
 
    // 定义切点,指定要监控哪些方法,这里指 com.example.bakery 包下所有以"make"开头的方法
    @Around("execution(* com.example.bakery.CakeChef.make*(..))")
    public Object timeCakeMaking(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        // 调用目标方法,即糕点师制作蛋糕的方法
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        System.out.println(joinPoint.getSignature().getName() + " 制作蛋糕耗时: " + (endTime - startTime) + "ms");
        return result;
    }
}

在上面的代码中,我们定义了一个 CakeTimerAspect 切面,它会在 com.example.bakery.CakeChef 类中所有以 make 开头的方法执行前后记录时间,就像一个计时器一样,可以自动记录每个蛋糕的制作时间。

糕点师和他的超级助手

想象一下,我们有一位糕点师(目标对象),他擅长制作各种美味的蛋糕。但是,除了制作蛋糕本身,他还需要做一些额外的工作:

  • 记录制作时间: 为了分析效率,他需要记录每个蛋糕的制作时间。
  • 清洁工作台: 每次制作蛋糕后,他都需要清洁工作台,保持卫生。

这些额外的工作就像 AOP 中的横切关注点,它们与制作蛋糕的核心业务逻辑不同,但却贯穿在整个制作过程中。

如果让糕点师自己手动处理这些额外工作,就会像我们之前说的,导致代码冗余,效率低下。

这时,AOP 就派上用场了!我们可以为糕点师配备一位超级助手(切面),这位助手可以帮糕点师自动完成那些额外的工作,而糕点师只需要专注于制作蛋糕即可。

超级助手如何工作?

让我们看看这位超级助手是如何帮助糕点师记录蛋糕制作时间的:

  1. 定义切面: 我们创建一个 CakeTimerAspect 类,这就是我们的超级助手。
  2. 定义切点: 我们需要告诉超级助手,他应该在哪些方法执行前后记录时间。这里我们用 @Around("execution(* com.example.bakery.CakeChef.make*(..))") 来表示,所有以 make 开头的方法都是需要记录时间的目标方法,就像告诉超级助手,只要糕点师开始制作蛋糕(执行以 make 开头的方法),你就开始计时。
  3. 编写横切逻辑: 在 timeCakeMaking 方法中,我们编写了记录时间的具体逻辑。joinPoint.proceed() 表示执行糕点师制作蛋糕的方法,而前后分别记录时间戳,就能计算出制作蛋糕的耗时。
// 超级助手:CakeTimerAspect
@Aspect
@Component
public class CakeTimerAspect {
 
    @Around("execution(* com.example.bakery.CakeChef.make*(..))")
    public Object timeCakeMaking(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis(); // 开始计时
        Object result = joinPoint.proceed(); // 糕点师制作蛋糕
        long endTime = System.currentTimeMillis(); // 结束计时
        System.out.println(joinPoint.getSignature().getName() + " 制作蛋糕耗时: " + (endTime - startTime) + "ms"); // 记录时间
        return result; 
    }
}

通过 AOP,我们就把记录时间的逻辑从糕点师制作蛋糕的代码中分离出来了,让糕点师可以更专注于他的核心工作。

3. 总结

IoC 和 AOP 是 Spring 框架的两大基石,它们为我们提供了一种更加优雅、高效的开发方式。

  • IoC 帮助我们管理对象的创建和依赖关系,降低了代码的耦合度,就像蛋糕店帮我们管理蛋糕制作一样方便。
  • AOP 帮助我们处理横切关注点,提高了代码的复用性和可维护性,就像计时器可以自动记录每个蛋糕的制作时间一样高效。

希望通过这篇文章,你对 IoC 和 AOP 有了更深入的理解。如果你想了解更多关于 Spring 框架的知识,欢迎关注我的公众号,我会定期分享更多精彩内容!

相关文章
|
19天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
116 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
7天前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
7天前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
19天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
19天前
|
缓存 Java 数据库
【Java面试题汇总】Spring篇(2023版)
IoC、DI、aop、事务、为什么不建议@Transactional、事务传播级别、@Autowired和@Resource注解的区别、BeanFactory和FactoryBean的区别、Bean的作用域,以及默认的作用域、Bean的生命周期、循环依赖、三级缓存、
【Java面试题汇总】Spring篇(2023版)
|
4天前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
13 4
|
9天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
527 7
|
7天前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
29 3
|
9天前
|
Java 程序员 UED
Java中的异常处理:从入门到精通
【9月更文挑战第23天】在Java编程的世界中,异常是程序执行过程中不可避免的事件,它们可能会中断正常的流程并导致程序崩溃。本文将通过浅显易懂的方式,引导你理解Java异常处理的基本概念和高级技巧,帮助你编写更健壮、更可靠的代码。我们将一起探索如何捕获和处理异常,以及如何使用自定义异常来增强程序的逻辑和用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的见解和实用的技巧。
28 4
|
20天前
|
Java 数据库连接 API
【Java笔记+踩坑】Spring Data JPA
从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。
【Java笔记+踩坑】Spring Data JPA
下一篇
无影云桌面