您的位置:首页 > 财经 > 金融 > 软件开发工程师薪资待遇_代理厦门网站设计公司_安卓优化大师旧版本_手机优化管家

软件开发工程师薪资待遇_代理厦门网站设计公司_安卓优化大师旧版本_手机优化管家

2025/4/19 8:25:09 来源:https://blog.csdn.net/qq_35971258/article/details/147340210  浏览:    关键词:软件开发工程师薪资待遇_代理厦门网站设计公司_安卓优化大师旧版本_手机优化管家
软件开发工程师薪资待遇_代理厦门网站设计公司_安卓优化大师旧版本_手机优化管家

大家好呀!今天我们来聊一个超级实用的技术话题 —— Spring Boot 中的依赖注入和Bean管理,特别是JavaConfig是如何一步步取代XML配置的。我知道很多小伙伴一听到"依赖注入"、"Bean管理"这些词就头大,别担心!我会用最简单的方式,就像教小朋友一样,带你彻底搞懂这些概念!😊

📚 第一章:什么是依赖注入?先来个生活小例子!

想象一下,你是一个小厨师👨🍳,要做一道美味的番茄炒蛋🍳。你需要什么呢?需要番茄、鸡蛋、油、盐对吧?这些"材料"就是你的"依赖"!

传统方式:你自己去菜市场买番茄、去养鸡场找鸡蛋、去超市买油和盐…累不累?😫

依赖注入方式:有个神奇的冰箱(Spring容器),里面已经准备好了所有材料,你只需要说"我要做番茄炒蛋",冰箱就自动把材料给你准备好!太方便了吧!😍

// 传统方式:自己创建所有依赖
Tomato tomato = new Tomato();
Egg egg = new Egg();
Oil oil = new Oil();
Salt salt = new Salt();
ScrambledEggWithTomato dish = new ScrambledEggWithTomato(tomato, egg, oil, salt);// 依赖注入方式:告诉Spring你需要什么,它自动给你
@Autowired
ScrambledEggWithTomato dish;  // Spring会自动把材料准备好并组装好这道菜!

看到区别了吗?依赖注入(Dependency Injection, DI)就是把对象所需要的其他对象(依赖)自动"注入"给它,而不是让它自己创建。这样代码更干净、更灵活!👍

🧩 第二章:什么是Bean?为什么需要管理它们?

在Spring的世界里,Bean就是由Spring容器管理的对象。就像冰箱里的食材一样,都是被冰箱(Spring容器)管理着的。

为什么需要管理Bean呢? 🤔

  1. 控制反转(IoC):对象的创建和管理权从程序员手里转交给了Spring容器
  2. 单例管理:确保某些重要的对象只有一个实例(比如数据库连接)
  3. 依赖解析:自动处理对象之间的复杂依赖关系
  4. 生命周期管理:控制对象的创建、初始化、销毁等过程

以前,我们用XML文件来配置这些Bean,就像写购物清单一样:

这种方式虽然能工作,但有好多问题:

  • XML文件会变得超级大,难以维护 📜
  • 没有类型安全检查,容易写错 ❌
  • 配置和代码分离,跳来跳去看很麻烦 🔍
  • 重构困难,改个类名要到处改XML 😫

💎 第三章:JavaConfig闪亮登场!✨

于是,Spring 3.0引入了JavaConfig,就是用Java类来代替XML配置!这就像是用智能手机📱取代老式按键手机一样,是巨大的进步!

JavaConfig的核心是@Configuration注解。看看同样的配置用Java怎么写:

@Configuration
public class KitchenConfig {@Beanpublic Tomato tomato() {return new Tomato();}@Beanpublic Egg egg() {return new Egg();}@Beanpublic Oil oil() {return new Oil();}@Beanpublic Salt salt() {return new Salt();}@Beanpublic ScrambledEggWithTomato dish(Tomato tomato, Egg egg, Oil oil, Salt salt) {return new ScrambledEggWithTomato(tomato, egg, oil, salt);}
}

哇!是不是清晰多了?👏 JavaConfig的好处太多了:

类型安全:编译器会检查类型对不对
易于重构:IDE可以自动重命名
更强大:可以写逻辑、调用方法等
更简洁:很多配置可以用注解简化
与代码在一起:不用在XML和Java间跳来跳去

🏗️ 第四章:Spring Boot如何更进一步简化配置?

Spring Boot在JavaConfig基础上又做了超级多的自动化!它就像个智能助手🤖,能根据你的依赖自动配置很多东西。

Spring Boot的核心魔法:

  1. 自动配置(Auto-configuration):根据classpath中的jar包自动配置Bean
  2. 起步依赖(Starter Dependencies):把常用依赖打包成"套餐"
  3. 条件化Bean(@Conditional):满足条件才创建Bean
  4. 属性配置(application.properties):外部化配置

举个例子,要配置一个数据库连接,以前要写一大堆:

@Configuration
public class DataSourceConfig {@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");dataSource.setUsername("root");dataSource.setPassword("password");return dataSource;}
}

而在Spring Boot中,只需要在application.properties中写:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

Spring Boot会自动帮你创建DataSource的Bean!如果连这些都不想写,用H2内存数据库的话,甚至什么都不用配置!😲

🎯 第五章:依赖注入的三种主要方式

Spring提供了三种主要的依赖注入方式,就像给冰箱里的食材三种不同的包装方式:

1. 构造器注入 (最推荐!👍)

public class ScrambledEggWithTomato {private final Tomato tomato;private final Egg egg;private final Oil oil;private final Salt salt;// 通过构造方法注入public ScrambledEggWithTomato(Tomato tomato, Egg egg, Oil oil, Salt salt) {this.tomato = tomato;this.egg = egg;this.oil = oil;this.salt = salt;}
}

优点

  • 不可变(final字段)
  • 完全初始化的对象
  • 易于测试
  • Spring官方推荐

2. Setter方法注入

public class ScrambledEggWithTomato {private Tomato tomato;private Egg egg;private Oil oil;private Salt salt;// 通过setter方法注入public void setTomato(Tomato tomato) {this.tomato = tomato;}public void setEgg(Egg egg) {this.egg = egg;}// 其他setter...
}

适用场景

  • 可选依赖
  • 需要重新配置的依赖

3. 字段注入 (不推荐❌)

public class ScrambledEggWithTomato {@Autowiredprivate Tomato tomato;@Autowiredprivate Egg egg;@Autowiredprivate Oil oil;@Autowiredprivate Salt salt;
}

为什么不推荐

  • 难以测试(必须用Spring容器)
  • 隐藏了依赖关系
  • 不能声明为final

🌈 第六章:Bean的作用域 - 控制Bean的生命周期

Spring中的Bean有不同的作用域,就像食材有不同的保质期一样:

  1. Singleton(单例):默认作用域,整个应用只有一个实例 🌟

    @Bean
    @Scope("singleton")  // 可以省略,默认就是
    public Tomato tomato() {return new Tomato();
    }
    
  2. Prototype(原型):每次请求都创建一个新实例 🔄

    @Bean
    @Scope("prototype")
    public Egg egg() {return new Egg();  // 每次获取都会new一个新的
    }
    
  3. Request:每个HTTP请求一个实例 (Web) 🌐

  4. Session:每个HTTP会话一个实例 (Web) 💻

  5. Application:每个ServletContext一个实例 (Web) 🖥️

  6. WebSocket:每个WebSocket会话一个实例 (Web) 🕸️

如何选择?

  • 无状态的服务类通常用singleton
  • 有状态的类考虑用prototype
  • Web相关的作用域用于Web环境

🛠️ 第七章:高级话题 - 条件化Bean与Profile

有时候我们想根据不同的环境创建不同的Bean,比如开发环境和生产环境用不同的数据源。Spring提供了两种主要方式:

1. @Profile - 根据环境激活Bean

@Configuration
public class DataSourceConfig {@Bean@Profile("dev")  // 开发环境用H2内存数据库public DataSource devDataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:schema.sql").build();}@Bean@Profile("prod")  // 生产环境用MySQLpublic DataSource prodDataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://prod-server:3306/mydb");dataSource.setUsername("prod-user");dataSource.setPassword("prod-password");return dataSource;}
}

激活profile的方式:

  • 命令行:--spring.profiles.active=dev
  • 配置文件:spring.profiles.active=dev
  • 环境变量:SPRING_PROFILES_ACTIVE=dev

2. @Conditional - 更灵活的条件判断

@Bean
@Conditional(MyCustomCondition.class)  // 自定义条件
public DataSource dataSource() {// ...
}public class MyCustomCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 这里写判断逻辑,返回true才创建Beanreturn context.getEnvironment().containsProperty("custom.property");}
}

Spring Boot提供了很多现成的条件注解:

  • @ConditionalOnClass:类路径有指定类时生效
  • @ConditionalOnMissingBean:没有指定Bean时生效
  • @ConditionalOnProperty:有指定配置属性时生效
  • @ConditionalOnWebApplication:是Web应用时生效

🔄 第八章:Bean的生命周期回调

有时候我们需要在Bean创建或销毁时做一些事情,Spring提供了几种方式:

  1. 实现接口

    public class MyBean implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {// 初始化逻辑}@Overridepublic void destroy() throws Exception {// 销毁逻辑}
    }
    
  2. 使用注解 (更推荐!):

    public class MyBean {@PostConstructpublic void init() {// 初始化逻辑}@PreDestroypublic void cleanup() {// 销毁逻辑}
    }
    
  3. 在@Bean注解中指定

    @Bean(initMethod = "init", destroyMethod = "cleanup")
    public MyBean myBean() {return new MyBean();
    }
    

执行顺序

  1. 构造函数
  2. @Autowired注入依赖
  3. @PostConstruct方法
  4. …使用Bean…
  5. @PreDestroy方法

🧠 第九章:常见问题与最佳实践

❓ 问题1:什么时候用@Component,什么时候用@Bean?

  • @Component:用在类上,让Spring自动扫描并创建Bean

    @Component
    public class MyService {// ...
    }
    
  • @Bean:用在@Configuration类的方法上,手动定义Bean创建逻辑

    @Configuration
    public class MyConfig {@Beanpublic MyService myService() {return new MyService();}
    }
    

经验法则

  • 自己写的类用@Component
  • 第三方库的类或需要复杂初始化的类用@Bean

❓ 问题2:循环依赖怎么办?

A依赖B,B又依赖A,这就形成了循环依赖。Spring能解决部分循环依赖,但最好避免!

解决方案

  1. 重新设计,打破循环
  2. 使用setter注入代替构造器注入
  3. 使用@Lazy延迟初始化
    @Component
    public class A {private final B b;public A(@Lazy B b) {  // 延迟初始化this.b = b;}
    }
    

❓ 问题3:如何选择XML和JavaConfig?

虽然JavaConfig是主流,但XML在以下情况仍有价值:

  • 遗留系统迁移
  • 需要在不修改代码的情况下更改配置
  • 某些复杂的Spring集成场景

但在新项目中,强烈建议使用JavaConfig!🎯

🚀 第十章:Spring Boot自动配置的魔法揭秘

Spring Boot的自动配置看起来像魔法,但其实原理很简单:

  1. @SpringBootApplication 是一个组合注解,包含:

    • @SpringBootConfiguration:标识这是配置类
    • @EnableAutoConfiguration:启用自动配置
    • @ComponentScan:自动扫描组件
  2. 自动配置原理

    • Spring Boot在spring-boot-autoconfigure.jar的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中定义了很多自动配置类
    • 这些类用@Conditional决定是否生效
    • 根据classpath中的类决定激活哪些配置
  3. 查看自动配置

    • 启动时添加--debug参数可以看到哪些自动配置生效了
    • 或者使用spring.autoconfigure.exclude排除某些自动配置
// 例如DataSourceAutoConfiguration的简化版
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic DataSource dataSource(DataSourceProperties properties) {// 根据配置创建DataSource}
}

🎁 第十一章:自定义Starter - 把你的配置分享给他人

如果你想把自己的配置打包成一个Starter给别人用,非常简单:

  1. 创建一个普通的Spring Boot项目

  2. 添加你的@Configuration类

  3. 在src/main/resources/META-INF下创建:

    • spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,写入你的配置类全名
    • additional-spring-configuration-metadata.json文件(可选,提供配置元数据)
  4. 打包发布,别人就可以通过引入你的starter来获得自动配置了!

📝 第十二章:总结 - JavaConfig vs XML 终极对决

特性JavaConfigXML配置
类型安全✅ 编译器检查❌ 运行时才发现错误
重构友好✅ IDE支持❌ 需要手动改
表达能力✅ 完整Java语法❌ 有限XML语法
灵活性✅ 可以写逻辑❌ 静态配置
可读性✅ 结构清晰❌ 嵌套复杂
配置集中度✅ 与代码一起❌ 分散在XML文件
学习曲线低(纯Java)中(特殊语法)
社区趋势主流逐渐淘汰

最终结论:在新项目中毫不犹豫选择JavaConfig!XML只应在维护旧系统时使用。🎉

🌟 第十三章:实战小练习

为了巩固知识,来做几个小练习吧!

练习1:创建一个配置类,定义以下Bean

  • 一个单例的UserService
  • 一个原型的Task
  • 一个依赖UserServiceProjectService

练习2:创建一个条件化Bean

  • 当系统属性"cache.enabled"=true时才创建CacheManager Bean

练习3:模拟一个Starter

  • 创建一个自动配置类,当classpath中有com.example.MyLib时自动配置MyLibAutoConfiguration

(答案可以在Spring官方文档或我的GitHub上找到哦~)

💖 最后的话

哇!不知不觉我们已经写了这么多内容!从最基础的依赖注入概念,到JavaConfig如何取代XML,再到Spring Boot的自动配置魔法,最后到创建自己的Starter。希望你现在对Spring的依赖注入和Bean管理有了清晰的认识!😊

记住,依赖注入的核心思想是"不要自己找依赖,让框架给你",而JavaConfig就是用Java代码清晰表达这种关系的最佳方式

如果你有任何问题,欢迎在评论区留言!我会尽力解答。也欢迎关注我的账号,我会持续分享更多Spring Boot和Java开发的干货内容!🚀

Happy Coding! 💻✨

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com