当前位置: 首页 > news >正文

Spring核心框架完全指南 - 基础知识全解析

📖 目录

🌟 Spring框架简介

🏗️ IoC容器详解

💉 依赖注入(DI)深入理解

⚙️ Bean配置与管理

🎯 Bean的作用域

🔄 Bean生命周期

🎭 面向切面编程(AOP)

📝 Spring注解详解

📁 资源管理

📢 事件机制

🔤 SpEL表达式语言

🎯 实战案例

📚 总结


🌟 Spring框架简介

什么是Spring?

Spring就像是Java开发的"超级管家",它帮我们管理对象的创建、依赖关系,让我们专注于业务逻辑。

生活中的类比

  • 没有Spring = 自己管理家务(买菜、做饭、打扫、洗衣服...)
  • 有了Spring = 请了专业管家(告诉需求,管家安排一切)

Spring的核心优势

// 传统Java开发的痛点
public class TraditionalCode {public void businessLogic() {// 手动创建对象DatabaseConnection db = new DatabaseConnection();db.connect("localhost", "user", "password");UserDao userDao = new UserDao();userDao.setConnection(db); // 手动设置依赖EmailService emailService = new EmailService();emailService.setSmtpServer("smtp.gmail.com");UserService userService = new UserService();userService.setUserDao(userDao); // 手动装配userService.setEmailService(emailService);// 业务逻辑userService.registerUser("张三");// 手动清理资源db.close();}
}// Spring帮我们解决的问题
@Service
public class SpringCode {@Autowiredprivate UserService userService; // Spring自动注入public void businessLogic() {// 直接使用,专注业务逻辑userService.registerUser("张三");// Spring自动管理资源}
}

Spring的两大核心特性

  1. IoC(控制反转) - 对象的创建和管理交给Spring
  2. AOP(面向切面编程) - 横切关注点的统一处理

🏗️ IoC容器详解

什么是IoC(控制反转)?

控制反转就是把对象的控制权从程序员手中转移给Spring容器。

形象比喻

  • 传统方式 = 自己开车(需要关注启动、换挡、刹车等细节)
  • IoC方式 = 坐出租车(告诉目的地,司机负责驾驶)

IoC容器的类型

// 1. BeanFactory - 基础容器(懒加载)
public class BeanFactoryExample {public static void main(String[] args) {// 创建资源对象Resource resource = new ClassPathResource("applicationContext.xml");// 创建BeanFactoryBeanFactory factory = new XmlBeanFactory(resource);// 只有在获取Bean时才创建对象UserService userService = (UserService) factory.getBean("userService");}
}// 2. ApplicationContext - 高级容器(立即加载)
public class ApplicationContextExample {public static void main(String[] args) {// 启动时就创建所有单例BeanApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = context.getBean("userService", UserService.class);}
}

ApplicationContext的实现类

// 1. 从类路径加载XML配置
ApplicationContext context1 = new ClassPathXmlApplicationContext("applicationContext.xml");// 2. 从文件系统加载XML配置
ApplicationContext context2 = new FileSystemXmlApplicationContext("/path/to/applicationContext.xml");// 3. 基于注解的配置
ApplicationContext context3 = new AnnotationConfigApplicationContext(AppConfig.class);// 4. Web应用上下文
// 在web.xml中配置,由Spring自动创建

💉 依赖注入(DI)深入理解

什么是依赖注入?

依赖注入是IoC的具体实现方式,就是Spring容器自动为对象提供它所需要的依赖对象。

生活类比

  • 手动依赖 = 自己买零件组装电脑
  • 依赖注入 = 买品牌机(厂商已配好兼容硬件)

依赖注入的三种方式

1. 构造器注入(最推荐)
@Component
public class OrderService {// 使用final确保依赖不可变private final PaymentService paymentService;private final InventoryService inventoryService;private final NotificationService notificationService;// Spring会自动调用这个构造器public OrderService(PaymentService paymentService, InventoryService inventoryService,NotificationService notificationService) {this.paymentService = paymentService;this.inventoryService = inventoryService;this.notificationService = notificationService;}public void processOrder(Order order) {// 检查库存if (inventoryService.checkStock(order.getProductId(), order.getQuantity())) {// 处理支付Payment payment = paymentService.processPayment(order);if (payment.isSuccessful()) {// 发送通知notificationService.sendOrderConfirmation(order);}}}
}// 构造器注入的优点:
// 1. 确保依赖不为null(构造时必须提供)
// 2. 支持final字段(不可变性)
// 3. 便于单元测试
// 4. 避免循环依赖问题
2. Setter注入
@Component
public class UserService {private EmailService emailService;private SmsService smsService;private AuditService auditService;// Setter注入 - 可选依赖@Autowired(required = false) // 可选依赖public void setEmailService(EmailService emailService) {this.emailService = emailService;}@Autowiredpublic void setSmsService(SmsService smsService) {this.smsService = smsService;}@Autowiredpublic void setAuditService(AuditService auditService) {this.auditService = auditService;}public void registerUser(User user) {// 保存用户saveUser(user);// 发送邮件(如果可用)if (emailService != null) {emailService.sendWelcomeEmail(user.getEmail());}// 发送短信smsService.sendWelcomeSms(user.getPhone());// 记录审计日志auditService.logUserRegistration(user.getId());}
}// Setter注入的优点:
// 1. 支持可选依赖
// 2. 可以重新配置依赖
// 3. 适合有很多可选依赖的场景
3. 字段注入(简单但不推荐)
@Component
public class ProductService {@Autowiredprivate ProductRepository productRepository;@Autowiredprivate PriceCalculator priceCalculator;@Autowiredprivate InventoryChecker inventoryChecker;public Product getProduct(Long id) {Product product = productRepository.findById(id);product.setPrice(priceCalculator.calculatePrice(product));product.setInStock(inventoryChecker.isInStock(product.getId()));return product;}
}// 字段注入的缺点:
// 1. 难以进行单元测试
// 2. 不支持final字段
// 3. 隐藏了依赖关系
// 4. 可能导致空指针异常

依赖注入的高级特性

1. 按类型注入 vs 按名称注入
// 按类型注入(默认)
@Component
public class OrderService {@Autowiredprivate PaymentService paymentService; // 按PaymentService类型注入
}// 按名称注入
@Component
public class OrderService {@Autowired@Qualifier("creditCardPaymentService") // 指定Bean名称private PaymentService paymentService;
}// 或者使用@Resource
@Component
public class OrderService {@Resource(name = "creditCardPaymentService")private PaymentService paymentService;
}
2. 集合注入
@Component
public class NotificationService {// 注入所有MessageSender实现@Autowiredprivate List<MessageSender> messageSenders;// 注入所有MessageSender的Map,key为Bean名称@Autowiredprivate Map<String, MessageSender> messageSenderMap;public void sendNotification(String message) {// 使用所有可用的发送器for (MessageSender sender : messageSenders) {sender.send(message);}}
}// 实现类
@Component("emailSender")
public class EmailSender implements MessageSender {public void send(String message) {System.out.println("通过邮件发送: " + message);}
}@Component("smsSender")
public class SmsSender implements MessageSender {public void send(String message) {System.out.println("通过短信发送: " + message);}
}
3. 条件注入
@Component
@ConditionalOnProperty(name = "app.feature.email", havingValue = "true")
public class EmailService {public void sendEmail(String message) {System.out.println("发送邮件: " + message);}
}@Component
@Profile("dev") // 只在dev环境生效
public class MockPaymentService implements PaymentService {public Payment processPayment(Order order) {System.out.println("模拟支付处理");return new Payment(order.getAmount(), true);}
}@Component
@Profile("prod") // 只在生产环境生效
public class RealPaymentService implements PaymentService {public Payment processPayment(Order order) {// 真实的支付处理逻辑return processRealPayment(order);}
}

⚙️ Bean配置与管理

Bean的定义方式

1. XML配置方式
<!-- applicationContext.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 基本Bean定义 --><bean id="userService" class="com.example.UserService"><!-- 属性注入 --><property name="emailService" ref="emailService"/><property name="maxRetryCount" value="3"/></bean><!-- 构造器注入 --><bean id="orderService" class="com.example.OrderService"><constructor-arg ref="paymentService"/><constructor-arg ref="inventoryService"/><constructor-arg value="100"/></bean><!-- 集合属性注入 --><bean id="notificationService" class="com.example.NotificationService"><property name="senders"><list><ref bean="emailSender"/><ref bean="smsSender"/></list></property><property name="config"><map><entry key="retryCount" value="3"/><entry key="timeout" value="5000"/></map></property></bean><!-- 内部Bean --><bean id="userController" class="com.example.UserController"><property name="userService"><bean class="com.example.UserService"><property name="emailService" ref="emailService"/></bean></property></bean><!-- Bean别名 --><alias name="userService" alias="userManager"/><!-- 启用组件扫描 --><context:component-scan base-package="com.example"/></beans>
2. 注解配置方式
// 配置类
@Configuration
@ComponentScan(basePackages = "com.example")
@PropertySource("classpath:application.properties")
public class AppConfig {// 读取配置文件中的值@Value("${database.url}")private String databaseUrl;@Value("${database.username}")private String username;@Value("${database.password}")private String password;// 手动定义Bean@Beanpublic DataSource dataSource() {HikariDataSource dataSource = new HikariDataSource();dataSource.setJdbcUrl(databaseUrl);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}// Bean之间的依赖@Beanpublic UserRepository userRepository() {return new UserRepository(dataSource());}// 条件Bean@Bean@ConditionalOnMissingBean(EmailService.class)public EmailService defaultEmailService() {return new DefaultEmailService();}// 主要Bean(当有多个同类型Bean时的默认选择)@Bean@Primarypublic PaymentService primaryPaymentService() {return new CreditCardPaymentService();}
}
3. 组件注解
// 基础组件
@Component
public class FileProcessor {public void processFile(String filename) {System.out.println("处理文件: " + filename);}
}// 服务层组件
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public void saveUser(User user) {userRepository.save(user);}
}// 数据访问层组件
@Repository
public class UserRepository {@Autowiredprivate DataSource dataSource;public void save(User user) {// 数据库保存逻辑}
}// 控制层组件(虽然这里不讲SpringMVC,但展示注解)
@Controller
public class UserController {@Autowiredprivate UserService userService;
}

Bean的初始化和销毁

1. 注解方式
@Component
public class DatabaseConnection {private Connection connection;// 初始化方法@PostConstructpublic void init() {System.out.println("初始化数据库连接");// 建立数据库连接this.connection = DriverManager.getConnection("...");}// 销毁方法@PreDestroypublic void cleanup() {System.out.println("关闭数据库连接");try {if (connection != null && !connection.isClosed()) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}
}
2. 接口方式
@Component
public class CacheManager implements InitializingBean, DisposableBean {private Map<String, Obje
http://www.xdnf.cn/news/986239.html

相关文章:

  • 关于界面存在AB测试后UI刷新空白的问题
  • 计算机网络 : 传输层协议UDP与TCP
  • 设计原则——KISS原则
  • 过拟合和欠拟合
  • RAG技术全解析:从概念到实践,构建高效语义检索系统——嵌入模型与向量数据库搭建指南
  • java每日精进 6.11【消息队列】
  • C++11的特性上
  • Cursor 编程实践 — 开发环境部署
  • 案例8 模型量化
  • 使用MyBatis-Plus实现数据权限功能
  • 【Unity3D优化】优化多语言字体包大小
  • swagger通过配置将enum自动添加到字段说明中
  • PHP如何检查一个字符串是否是email格式
  • 【微信小程序】| 在线咖啡点餐平台设计与实现
  • 华为云Flexus+DeepSeek征文 | 基于华为云ModelArts Studio打造AingDesk AI聊天助手
  • list类型
  • SCADA|测试KingSCADA4.0信创版采集汇川PLC AC810数据
  • 开源夜莺支持MySQL数据源,更方便做业务指标监控了
  • xss分析
  • C2f模块 vs Darknet-53——YOLOv8检测效率的提升
  • 9.IP数据包分片计算
  • HNCTF2025 - Misc、Osint、Crypto WriteUp
  • 第三讲 基础运算之整数运算
  • 什么是数字化项目风险管理?如何实现项目风险管理数字化?
  • IIS 实现 HTTPS:OpenSSL证书生成与配置完整指南
  • 突然虚拟机磁盘只剩下几十K
  • [特殊字符] React 与 Vue 源码级对比:5大核心差异与实战选择指南
  • # include<heαd.h>和# include″heαd.h″的区别
  • 成都国际数字影像产业园孵化培育模式的探索与突破
  • 人机交互设计知识点总结