引言
时光匆匆流逝,不知不觉笔者已有小半个月未更新内容啦。也许没人在意笔者为何没更新,但笔者还是想告知一下,这段时间笔者一方面在为期末考试做准备,另一方面也在梳理学习笔记呢。
现在,决定开启Spring系列博客的正式征程啦。
本篇将会聚焦于Spring的核心思想之一——IoC(控制反转)与DI(依赖注入)哟。期望能和大家一同深入探究,让Spring的“魔法”不再遥不可及呢。
为何我们需要Spring?
在深入研习Spring的IoC(控制反转)和DI(依赖注入)之前呢,咱们先来看一个简单的对比,你马上就能感受到Spring的魅力啦。
传统方式对比Spring方式
传统的Java开发模式:
public class OrderController {
private OrderService orderService;
private PaymentService paymentService;
private EmailService emailService;
public OrderController() {
// 手动创建所有依赖对象
this.orderService = new OrderService();
this.paymentService = new PaymentService();
this.emailService = new EmailService();
}
public void processOrder(Order order) {
orderService.saveOrder(order);
paymentService.processPayment(order);
emailService.sendConfirmation(order);
}
}
使用Spring框架:
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private PaymentService paymentService;
@Autowired
private EmailService emailService;
@PostMapping("/orders")
public void processOrder(@RequestBody Order order) {
orderService.saveOrder(order);
paymentService.processPayment(order);
emailService.sendConfirmation(order);
}
}
看起来差别不大?咱们接着往下瞧哦…
传统开发模式的痛点
1. 对象创建的难题
设想一下,当你的项目变得复杂时:
public class OrderService {
private UserRepository userRepository;
private ProductRepository productRepository;
private InventoryService inventoryService;
private DiscountService discountService;
private AuditService auditService;
public OrderService() {
// 每个依赖都得手动创建
this.userRepository = new UserRepository();
this.productRepository = new ProductRepository();
this.inventoryService = new InventoryService();
this.discountService = new DiscountService();
this.auditService = new AuditService();
// 但是等等...这些服务可能还有自身的依赖呢!
// UserRepository或许需要DataSource
// InventoryService可能需要CacheManager
// 这会形成一个复杂的依赖链哟...
}
}
问题很明显啦:
- 代码臃肿:构造函数被大量的对象创建代码污染啦
- 硬编码依赖:要是要更换实现,就得修改源代码呢
- 测试困难:没办法轻易mock依赖对象来进行单元测试啦
- 维护噩梦:依赖关系复杂,牵一发而动全身呢
2. 配置困境
还记得那些冗长的XML配置文件不?
<!-- 传统的XML配置,数百行的重复配置 -->
<bean id="dataSource" class="com.mysql.jdbc.Driver">
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="userRepository" class="com.example.UserRepository">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="orderService" class="com.example.OrderService">
<property name="userRepository" ref="userRepository"/>
<property name="productRepository" ref="productRepository"/>
<!-- ...更多配置... -->
</bean>
3. 测试的苦恼
// 传统方式下的单元测试
public class OrderServiceTest {
@Test
public void testCreateOrder() {
// 为了测试OrderService,得创建所有的依赖
UserRepository userRepo = new UserRepository();
ProductRepository productRepo = new ProductRepository();
InventoryService inventoryService = new InventoryService();
// ...还有更多依赖
OrderService orderService = new OrderService();
// 测试代码比业务代码还复杂哟!
}
}
Spring带来的变革性改变
现在呢,咱们来瞧瞧Spring是怎样优雅地解决这些问题的哟:
1. 告别手动创建对象
@Service
public class OrderService {
@Autowired
private UserRepository userRepository;
@Autowired
private ProductRepository productRepository;
@Autowired
private InventoryService inventoryService;
// 构造函数变得简洁啦
// 所有依赖由Spring自动注入
public void createOrder(Order order) {
// 专注于业务逻辑,而不是对象创建啦
User user = userRepository.findById(order.getUserId());
// ...业务逻辑
}
}
2. 配置变简单啦
@Configuration
@ComponentScan("com.example")
public class AppConfig {
// 一个注解胜过千行XML哟
}
// 或者更简单,使用Spring Boot
@SpringBootApplication
public class Application {
// 零配置启动啦!
}
3. 测试变轻松啦
@ExtendWith(SpringExtension.class)
class OrderServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private OrderService orderService;
@Test
void testCreateOrder() {
// 轻松mock依赖,专注测试业务逻辑啦
when(userRepository.findById(1L)).thenReturn(mockUser);
orderService.createOrder(testOrder);
verify(userRepository).findById(1L);
}
}
真实场景模拟:一个电商系统的对比
咱们通过一个真实的电商系统场景来感受这种差异哈:
咱们假设一个用户下单,系统需要:
-
扣减库存
-
执行支付
-
返回下单结果
传统方式的订单处理类:
// 传统方式:自己创建依赖对象
public class OrderService {
private PaymentService paymentService;
private InventoryService inventoryService;
public OrderService() {
this.paymentService = new PaymentService(); // 主动创建依赖对象
this.inventoryService = new InventoryService();
}
public void createOrder() {
inventoryService.deductStock();
paymentService.pay();
System.out.println("订单创建成功!");
}
public static void main(String[] args) {
OrderService orderService = new OrderService();
orderService.createOrder();
}
}
class PaymentService {
public void pay() {
System.out.println("支付成功!");
}
}
class InventoryService {
public void deductStock() {
System.out.println("库存扣减成功!");
}
}
问题来啦:
代码耦合严重,OrderService 无法方便地更换或测试依赖组件 。
不利于维护,不利于扩展,不易于单元测试。
Spring方式的订单处理类:
1. 定义各个组件
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
@Autowired
private InventoryService inventoryService;
public void createOrder() {
inventoryService.deductStock();
paymentService.pay();
System.out.println("订单创建成功!");
}
}
@Service
class PaymentService {
public void pay() {
System.out.println("支付成功!");
}
}
@Service
class InventoryService {
public void deductStock() {
System.out.println("库存扣减成功!");
}
}
2. 启动类模拟运行
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class ECommerceApp {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ECommerceApp.class, args);
OrderService orderService = context.getBean(OrderService.class);
orderService.createOrder();
}
}
你准备好了吗?
看到这儿,你是否已经感受到了Spring框架的强大魅力啦?它不只是一个工具呢,更是一种编程思想的革新哟。
Spring解决的可不只是技术问题呢,更是开发效率和代码质量的问题哟:
- 让开发者专注业务逻辑,而不是基础设施啦
- 让代码更加简洁、优雅、可维护啦
- 让测试变得简单,提高代码质量啦
- 让团队协作更加高效啦
那么问题来啦:Spring是怎样做到这一切的呢?
答案就在IoC(控制反转)和DI(依赖注入)这两个核心概念里哟。弄懂了它们,你就弄懂了Spring的灵魂啦,也就掌握了现代Java开发的精髓啦。
接下来呢,咱们就深入探究这个让Java开发变得如此优雅的奥秘哟!
结尾:
要是你读到这儿啦,可别因为戛然而止觉得惊讶哦,因为笔者打算在下一篇博客里详细介绍Ioc & DI呢
所以这是引子博客哟,笔者期望读者明白为啥需要IoC和DI,珍惜Spring带来的便利呢。