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

Spring Java配置:告别XML新时代

以下内容是 Spring Framework 官方文档中关于“基于 Java 的容器配置”1.12. Java-based Container Configuration)的一节,它系统地介绍了如何使用 Java 代码和注解 来替代传统的 XML 配置文件(如 applicationContext.xml),实现对 Spring IoC 容器的完全编程式配置。

下面我将用清晰、结构化的方式为你逐段解析这段内容的核心思想,并帮助你理解:


🌟 总体目标:用 Java 代替 XML 配置

在早期 Spring 版本中,我们通过编写 beans.xml 文件来定义 Bean:

<beans><bean id="myService" class="com.acme.MyServiceImpl"/>
</beans>

但从 Spring 3.0 开始,官方推荐使用 纯 Java 类 + 注解 的方式来配置 Spring 容器。这种方式更类型安全、易于调试、支持重构,也更适合现代开发。

✅ 目标:实现 零 XML 的 Spring 应用。


🔑 核心概念:@Configuration@Bean

这是整个 Java 配置模式的基石。

注解作用
@Configuration表示这个类是一个“配置类”,相当于一个 XML 配置文件
@Bean表示这个方法返回的对象应该被 Spring 容器管理(即注册为一个 Bean)

示例代码

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

等价于以下 XML:

<beans><bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>

📌 关键点:

  • 方法名 myService() 就是 Bean 的名字(ID)。
  • 返回值 MyServiceImpl() 是实际创建的 Bean 实例。
  • Spring 会把这个方法的返回值放入 IoC 容器中进行管理。

⚖️ “全功能” vs “轻量级” 模式(Full vs Lite Mode)

这是一个非常重要的区别!

模式条件特性
全功能模式(Full)类上有 @Configuration支持方法间依赖调用(内部调用会被代理拦截)
轻量模式(Lite)类上没有 @Configuration(比如只是 @Component 或普通类)不支持跨方法依赖,仅作为工厂方法使用

🧩 全功能模式(推荐)

@Configuration
public class AppConfig {@Beanpublic DataSource dataSource() {return new EmbeddedDatabaseBuilder().build();}@Beanpublic JdbcTemplate jdbcTemplate() {return new JdbcTemplate(dataSource()); // 调用另一个 @Bean 方法}
}

✅ 在 jdbcTemplate() 中调用 dataSource(),Spring 会确保返回的是同一个单例 Bean(通过 CGLIB 动态代理实现)。

❌ 如果你在“轻量模式”下这样做:

@Component  // 注意:不是 @Configuration
public class LiteConfig {@Beanpublic DataSource dataSource() { ... }@Beanpublic JdbcTemplate jdbcTemplate() {return new JdbcTemplate(dataSource()); // ❌ 新建了一个实例!}
}

⚠️ 这里的 dataSource() 是普通 Java 方法调用,每次都会新建对象,破坏了 Singleton 语义!

📌 所以结论:

尽量把 @Bean 方法写在 @Configuration 类中,避免意外行为。


🚀 如何启动容器?使用 AnnotationConfigApplicationContext

以前我们用:

new ClassPathXmlApplicationContext("beans.xml");

现在我们可以用:

new AnnotationConfigApplicationContext(AppConfig.class);

这意味着:直接传入 Java 配置类来初始化 Spring 容器

支持多种输入类型:

  • @Configuration
  • @Component 类(含 @Service, @Repository 等)
  • 使用 JSR-330 注解(如 @Named)的类
✅ 方式一:构造函数传参
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class, UserService.class, OrderService.class
);
✅ 方式二:编程式注册(register)
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.register(OtherConfig.class);
ctx.refresh(); // 必须手动刷新

💡 refresh() 触发 Bean 的加载与初始化。

✅ 方式三:启用组件扫描(scan)
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme"); // 扫描包下的所有 @Component/@Configuration 类
ctx.refresh();

这相当于 XML 中的:

<context:component-scan base-package="com.acme"/>

🔍 启用组件扫描:@ComponentScan

如果你想让 Spring 自动发现并注册带有 @Component@Service 等注解的类,可以在配置类上加上:

@Configuration
@ComponentScan(basePackages = "com.acme")
public class AppConfig {
}

这样就不需要手动一个个写 @Bean 了。

✅ 推荐做法:主配置类加 @ComponentScan,业务类加 @Service / @Repository 等。

📌 注意:@Configuration 本身也被 @Component 注解标记,所以它也会被扫描到。


☁️ Web 应用支持:AnnotationConfigWebApplicationContext

对于 Web 项目(如 Spring MVC),你需要一个能运行在 Servlet 容器中的上下文。

Spring 提供了对应的 Web 版本:

org.springframework.web.context.support.AnnotationConfigWebApplicationContext

配置 web.xml 示例

<web-app><!-- 指定根容器使用 Java 配置 --><context-param><param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></context-param><!-- 指定配置类 --><context-param><param-name>contextConfigLocation</param-name><param-value>com.acme.AppConfig</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- DispatcherServlet 也使用 Java 配置 --><servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextClass</param-name><param-value>...AnnotationConfigWebApplicationContext</param-value></init-param><init-param><param-name>contextConfigLocation</param-name><param-value>com.acme.web.MvcConfig</param-value></init-param></servlet>
</web-app>

📌 这样就可以完全摆脱 spring-servlet.xml 文件!


📦 更高级的主题(后续小节预告)

文档还提到了一些进阶功能,虽然没展开讲,但值得了解:

主题说明
Bean Definition Profiles (@Profile)根据环境激活不同配置(如 dev/test/prod)
PropertySource 抽象加载属性文件(.properties.yml
@PropertySource将外部配置文件加载进 Spring 环境
占位符解析 (${})@Value 中使用 ${jdbc.url} 获取配置值

这些将在后续章节详细介绍。


✅ 总结:你应该怎么理解?

传统 XML 配置新的 Java 配置
<beans> 标签@Configuration
<bean> 标签@Bean 方法
<context:component-scan>@ComponentScan 注解或 ctx.scan()
ClassPathXmlApplicationContextAnnotationConfigApplicationContext
Web XML 配置AnnotationConfigWebApplicationContext

🎯 最佳实践建议

  1. 优先使用 @Configuration + @Bean 来做核心组件配置(如数据源、JPA、Redis 等)。
  2. 使用 @ComponentScan 自动扫描业务组件(Service、Repository)。
  3. 避免在非 @Configuration 类中使用 @Bean,除非你明确知道自己在做什么(lite 模式风险)。
  4. Web 项目中使用 AnnotationConfigWebApplicationContext 替代 XML。
  5. 结合 @Profile@PropertySource 实现多环境配置。

🔄 对比记忆表

功能XML 写法Java 注解写法
定义配置文件<beans>@Configuration
定义一个 Bean<bean class="X"/>@Bean X x() { return new X(); }
组件扫描<context:component-scan base-package="x"/>@ComponentScan("x")
创建容器new ClassPathXmlApplicationContext("x.xml")new AnnotationConfigApplicationContext(X.class)
Web 容器XmlWebApplicationContextAnnotationConfigWebApplicationContext

💬 结语

你现在看到的是 Spring 从“XML 驱动”转向“Java 驱动”的关键设计。这套机制后来成为 Spring Boot 自动配置的基础

如果你正在学习 Spring Boot,你会发现它的自动配置类(@Configuration 类)大量使用了这种模式。


需要我帮你画一张思维导图?或者写一个完整的例子(包含多个配置类、组件扫描、属性注入)来演示整个流程吗?

http://www.dtcms.com/a/528031.html

相关文章:

  • Flutter 异步进阶:Isolate 与 compute 的性能优化实践
  • 太原网站建设模板网页制作的公司怎么注册
  • Linux拓展
  • 亚马逊云渠道商:本地SSD缓存如何保障数据安全?
  • seo外包公司排名深圳网站优化最好的方法
  • SQL优化详解与案例、以及索引失效场景;
  • llama.cpp:Linux_x86端测试Qwen2.5-Omni
  • Java-160 MongoDB副本集部署实战 单机三实例/多机同法 10 分钟起集群 + 选举/读写/回滚全流程
  • 使用RedisTemplate设计一个消息队列?
  • 海龟交易系统R
  • 【攻防实战】Redis未授权RCE联动metasploit打穿三层内网(上)
  • 织梦网站图片修改不了wordpress模板开发 2016
  • .Net Framework 3.5下载安装教程(附安装包)
  • pycharm远程提交Git
  • PLM实施专家宝典:离散制造企业工程变更的“流程金融”方案
  • Orleans分布式系统架构详细分析
  • 建设网站的价钱深圳宝安上市公司网站建设报价
  • F034 vue+neo4j 体育知识图谱系统|体育文献知识图谱vue+flask知识图谱管理+d3.js可视化
  • 【day10】分治
  • 【Go】C++转Go:数据结构练习(一)排序算法
  • 每天学习一个新注解——@SafeVarargs
  • valgrind交叉编译android版本
  • 公司网站开发设计题目来源怎么写佛山免费建站怎样
  • 构建AI智能体:七十四、探索AI新纪元:扣子平台让想法到智能应用的极简之旅
  • P2119 [NOIP 2016 普及组] 魔法阵
  • 数据结构13:排序
  • 网站搭建 里短信wordpress acf破解版
  • 【C/C++】数据在内存中的存储
  • 我们项目中如何运用vueuse
  • 【开发者导航】集成多引擎与离线查询的macOS开源翻译工具:Easydict