springboot重点

springboot重点

下面简单介绍一下 Spring Boot 框架中两个至关重要的设计理念:IOC(控制反转)和 AOP(面向切面编程)。


控制反转(IOC)

  • 定义: 控制反转是一种设计模式,其核心思想是将对象的创建与管理交由 Spring 容器处理,而非在代码中硬编码实例化。也就是说,应用程序不再主动创建依赖对象,而是通过依赖注入(DI)的方式,由容器在运行时将所需组件动态注入到目标对象中。
  • 优点:
    • 解耦合: 各个组件间不再直接依赖具体实现,使得模块之间的耦合度大幅降低。
    • 便于测试: 由于依赖关系通过注入管理,替换为 Mock 对象或其他实现就变得简单。
    • 灵活性和可维护性: 组件的生命周期与配置完全交由 Spring 管理,开发者只需专注于业务逻辑,实现“关注点分离”。

就像拥有一位超级管家,自动处理组件之间的依赖关系,让开发者能够专注于“创意设计”而非“后勤保障”。


面向切面编程(AOP)

  • 定义: AOP 是一种编程范式,==用于将那些横切关注点(例如日志记录、事务管理、安全控制等)与核心业务逻辑分离==。通过在代码运行的不同阶段(方法调用前、后或异常时)动态地插入特定的“切面”,AOP 实现了业务逻辑与通用功能的解耦。
  • 工作原理:
    • 切面(Aspect): 定义了横切关注点的逻辑,包含通知(Advice)和切点(Pointcut)。
    • 通知(Advice): 指定在特定时刻执行的操作,比如方法执行前后。
    • 切点(Pointcut): 定位到需要增强的目标方法。
    • 代理模式: Spring 通常通过代理技术,在调用目标方法时先执行切面中的额外逻辑,再调用目标方法,从而实现“无侵入”式的功能扩展。
  • 优点:
    • 代码复用: 横切关注点集中管理,避免在每个业务方法中重复编写相同的代码。
    • 提高可维护性: 修改公共逻辑时只需调整一个切面即可,无需触及核心业务代码。
    • 业务逻辑纯粹: 让代码更易读、更专注于实现核心业务,增强整体架构的清晰度。

想象一下,AOP 就像给每个方法装上了“智能护盾”,在不干扰核心功能的同时,自动处理那些重复又关键的横向任务。


小结

  • IOC 使得组件之间的依赖关系由 Spring 容器管理,解除了组件之间的硬编码依赖,极大地提升了代码的灵活性和测试性。
  • AOP 则将横切关注点(如日志、事务、安全等)抽离出来,以切面的形式统一管理,让业务逻辑更加专注和清晰。

1. IOC 示例

在 IOC(控制反转)中,组件之间的依赖关系由 Spring 容器管理。举个例子,我们可以定义一个业务逻辑类(Service),然后在 Controller 中通过依赖注入(DI)的方式使用它。如下代码展示了如何用注解实现这一过程:

java
复制代码
// UserService.java package com.example.demo.service; import org.springframework.stereotype.Service; @Service // 将该类注册为 Spring Bean public class UserService { public String getUserInfo() { return "这是用户信息。"; } }
java
复制代码
// UserController.java package com.example.demo.controller; import com.example.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController // 定义为 REST 风格的控制器 public class UserController { @Autowired // 依赖注入,将 UserService 注入到 UserController 中 private UserService userService; @GetMapping("/user") public String getUser() { // 通过容器管理的 UserService 获取用户信息 return userService.getUserInfo(); } }

说明:

  • @Service 注解告诉 Spring,该类是一个业务层组件,容器将自动创建其实例。
  • @Autowired 注解用于自动注入依赖,使得 UserController 不需要自己实例化 UserService,从而实现了 IOC。
  • 整个过程使得组件之间的耦合度降低,方便后续扩展和单元测试。

2. AOP 示例

AOP(面向切面编程)用于将横切关注点(如日志、事务、安全等)从业务逻辑中分离出来。下面的示例展示了如何利用 AOP 实现方法调用前的日志记录。

java
复制代码
// LoggingAspect.java package com.example.demo.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect // 声明一个切面 @Component // 让 Spring 管理这个切面组件 public class LoggingAspect { // 定义切点:拦截 com.example.demo.service 包下所有方法的执行 @Before("execution(* com.example.demo.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("【日志】调用方法:" + joinPoint.getSignature().getName()); } }

说明:

  • @Aspect 注解表明该类是一个切面,包含了横切逻辑。
  • @Before 注解定义了一个前置通知,即在目标方法执行前会执行 logBefore 方法。
  • 切点表达式 "execution(* com.example.demo.service.*.*(..))" 表示拦截 com.example.demo.service 包中所有类的任意方法。
  • 通过这种方式,我们不需要在每个业务方法中手动添加日志记录代码,而是由 AOP 自动处理,从而保持业务代码的简洁与专注。

总结

  • IOC 示例: 通过注解 @Service@Autowired,Spring 自动管理组件的实例化和依赖注入,解耦了组件之间的关系。
  • AOP 示例: 通过定义切面和通知(如 @Before),Spring AOP 在方法调用前统一处理横切关注点(例如日志记录),使业务逻辑更纯粹。

1. 业务接口与多实现(IOC 实践)

首先定义一个支付服务接口,并提供两种实现——分别模拟信用卡和 PayPal 的支付处理。利用 @Service 注解,Spring 容器将自动将它们纳入管理。

java
复制代码
// PaymentService.java package com.example.demo.service; public interface PaymentService { String processPayment(double amount); }
java
复制代码
// CreditCardPaymentService.java package com.example.demo.service; import org.springframework.stereotype.Service; @Service("creditCardPaymentService") public class CreditCardPaymentService implements PaymentService { @Override public String processPayment(double amount) { // 模拟信用卡支付的处理过程 try { Thread.sleep(200); // 模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } return "信用卡支付 $" + amount + " 成功处理。"; } }
java
复制代码
// PaypalPaymentService.java package com.example.demo.service; import org.springframework.stereotype.Service; @Service("paypalPaymentService") public class PaypalPaymentService implements PaymentService { @Override public String processPayment(double amount) { // 模拟 PayPal 支付的处理过程 try { Thread.sleep(300); // 模拟延时 } catch (InterruptedException e) { e.printStackTrace(); } return "PayPal 支付 $" + amount + " 成功处理。"; } }

在上述代码中,通过 @Service("...") 为每个实现指定了标识符,方便后续在依赖注入时精准选择所需实现。

2. 核心业务处理类与依赖注入

接下来定义一个业务处理类 PaymentProcessor,它通过构造器注入方式使用了 PaymentService 接口。这里我们利用 @Qualifier 指定使用信用卡支付服务(您可灵活切换到其他实现而不改动核心逻辑)。

java
复制代码
// PaymentProcessor.java package com.example.demo.processor; import com.example.demo.service.PaymentService; import com.example.demo.annotation.TrackTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component public class PaymentProcessor { private PaymentService paymentService; // 通过 @Qualifier 指定具体的实现,这就是 IOC 的魅力:解耦依赖! @Autowired public PaymentProcessor(@Qualifier("creditCardPaymentService") PaymentService paymentService) { this.paymentService = paymentService; } // 业务方法上标记自定义注解,用于 AOP 切面监控执行时间 @TrackTime public void process(double amount) { String result = paymentService.processPayment(amount); System.out.println(result); } }

通过这种设计,即便将来支付方式发生变化,只需调整依赖注入的配置或切换 @Qualifier 参数,业务逻辑代码完全无需修改。

3. 自定义注解与 AOP 环绕通知

为了监控方法执行时间,我们定义一个自定义注解 @TrackTime,并编写 AOP 切面 LoggingAspect。切面中采用了 @Around 环绕通知,在方法执行前后计算耗时,并记录相关日志。

java
复制代码
// TrackTime.java package com.example.demo.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface TrackTime { }
java
复制代码
// LoggingAspect.java package com.example.demo.aspect; import com.example.demo.annotation.TrackTime; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { @Around("@annotation(trackTime)") public Object logExecutionTime(ProceedingJoinPoint joinPoint, TrackTime trackTime) throws Throwable { long start = System.currentTimeMillis(); System.out.println("【AOP日志】方法 " + joinPoint.getSignature().getName() + " 开始执行..."); Object proceed = joinPoint.proceed(); // 执行目标方法 long executionTime = System.currentTimeMillis() - start; System.out.println("【AOP日志】方法 " + joinPoint.getSignature().getName() + " 执行完毕,耗时 " + executionTime + " 毫秒"); return proceed; } }

这种设计不仅帮助企业监控关键业务方法的性能,还能方便地在需要时添加更多横切逻辑(如权限验证、异常监控等),保持核心代码的整洁。

4. 控制器入口

最后,我们通过一个 REST 接口来触发支付流程,测试整个系统的协作效果。

java
复制代码
// PaymentController.java package com.example.demo.controller; import com.example.demo.processor.PaymentProcessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class PaymentController { @Autowired private PaymentProcessor paymentProcessor; @GetMapping("/pay") public String makePayment(@RequestParam("amount") double amount) { paymentProcessor.process(amount); return "支付流程已触发!"; } }

访问 /pay?amount=100 后,您将看到支付信息输出,并在控制台打印出 AOP 切面的执行日志。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP