news 2026/5/9 22:32:34

Spring 第三天:注解驱动开发与整合 MyBatis/JUnit

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring 第三天:注解驱动开发与整合 MyBatis/JUnit

前言

前面两天我们用 XML 配置文件扎实掌握了 Spring 的 IoC 和 DI。但配置写多了总感觉繁琐,Spring 早就想到了这一点,从 2.5 版开始全面支持注解,3.0 版更是实现了纯注解开发,让我们彻底告别 XML。

今天我要带你跟上时代的步伐,用注解重新定义 Bean、注入依赖,还会把第三方的 Druid 数据源、MyBatis 甚至 Junit 都整合进 Spring 容器。学完这一章,你就能体会到 Spring Boot 自动配置的雏形了。

💬课前唠一唠:前两天写 XML 写到手酸了吗?今天换成注解,你最想先“删除”哪段 XML 配置?评论区说说你的怨念,看看有没有同病相怜的伙伴。


一、IOC/DI 配置管理第三方 Bean

之前我们把自家写的类交给 Spring 管,那第三方的 jar 包里的类(比如 Druid 连接池)怎么管?

1.1 案例:管理 Druid 数据源

需求:把 Druid 连接池对象交给 Spring 的 IoC 容器。

步骤

  1. 导入依赖
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>
  1. applicationContext.xml中配置 Bean,注入数据库四要素
<beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"><propertyname="driverClassName"value="com.mysql.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost:3306/spring_db"/><propertyname="username"value="root"/><propertyname="password"value="root"/></bean>
  1. 从容器获取并打印
DataSourcedataSource=(DataSource)ctx.getBean("dataSource");System.out.println(dataSource);

🧪动手尝试:换成 C3P0 试试?管理它的类是ComboPooledDataSource,注意属性名不一样(driverClass,jdbcUrl等)。你会发现 C3P0 初始化就要求驱动,需要额外引入mysql-connector-java

1.2 加载 properties 文件

把数据库连接信息硬编码在 XML 里不利于维护,咱们把它提到jdbc.properties里。

步骤

  1. 创建jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db jdbc.username=root jdbc.password=root
  1. 在 XML 中开启context命名空间,并加载文件
<beans...xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="... spring-context.xsd"><!-- 加载 properties,system-properties-mode="NEVER" 防止系统环境变量覆盖 --><context:property-placeholderlocation="jdbc.properties"system-properties-mode="NEVER"/></beans>
  1. ${key}引用值
<propertyname="driverClassName"value="${jdbc.driver}"/><propertyname="url"value="${jdbc.url}"/><propertyname="username"value="${jdbc.username}"/><propertyname="password"value="${jdbc.password}"/>

多个配置文件加载方式

<!-- 方式一:用逗号分隔 --><context:property-placeholderlocation="jdbc.properties,jdbc2.properties"/><!-- 方式二:通配符 *.properties(不建议) --><!-- 方式三:标准写法,classpath: 开头 --><context:property-placeholderlocation="classpath:*.properties"/>

⚠️注意username这个 key 会跟系统环境变量冲突,最好用jdbc.username这类带前缀的名字,或加上system-properties-mode="NEVER"


二、核心容器

我们已经用过ApplicationContext,这里系统梳理一下容器的创建和获取 Bean 的方式。

2.1 容器的创建方式

  • 推荐ClassPathXmlApplicationContext("applicationContext.xml")– 从类路径加载
  • 了解FileSystemXmlApplicationContext("绝对路径")– 从文件系统加载,路径写死不推荐

2.2 获取 Bean 的三种方式

// 方式1:按名称,需要强转BookDaobookDao=(BookDao)ctx.getBean("bookDao");// 方式2:按名称 + 类型,省去强转BookDaobookDao=ctx.getBean("bookDao",BookDao.class);// 方式3:按类型,容器中该类型 Bean 必须唯一BookDaobookDao=ctx.getBean(BookDao.class);

2.3 容器层次与 BeanFactory

  • BeanFactory:IoC 容器的顶层接口,延迟加载(获取 bean 时才创建)
  • ApplicationContext:是BeanFactory的子接口,立即加载(初始化容器时就创建所有单例 bean)

若想让ApplicationContext也延迟加载某个 bean,可在配置中加lazy-init="true"

💡小结:日常开发多采用ClassPathXmlApplicationContext和按类型获取 bean 的方式。


三、IOC/DI 注解开发

终于不用写 XML 里的<bean>了!Spring 提供了几个注解帮我们自动注册 Bean。

3.1 注解定义 Bean

  1. 在类上添加@Component("bookDao"),相当于<bean id="bookDao" class="...">
  2. 在 xml 中配置包扫描,让 Spring 能发现这些注解
<context:component-scanbase-package="com.itheima"/>
  1. 以后直接在类上写注解即可。

常用分层注解(功能同@Component,只是语义更明确)

  • @Controller:表现层
  • @Service:业务层
  • @Repository:数据层

如果不指定名称,默认是类名首字母小写。

3.2 纯注解开发(告别 XML)

配置类完全替代 XML。

@Configuration// 标志这是一个配置类,相当于 applicationContext.xml@ComponentScan("com.itheima")// 包扫描publicclassSpringConfig{}

启动容器改用

ApplicationContextctx=newAnnotationConfigApplicationContext(SpringConfig.class);

🔄对比:XML →ClassPathXmlApplicationContext;配置类 →AnnotationConfigApplicationContext

3.3 bean 作用范围与生命周期

作用范围:默认单例,用@Scope("prototype")改为非单例。

生命周期

  • 初始化:@PostConstruct标注的方法(构造后执行)
  • 销毁前:@PreDestroy标注的方法(容器关闭前执行)

注意:从 JDK9 开始需要额外引入javax.annotation-api包,否则这两个注解找不到。

3.4 注解依赖注入

自动装配(按类型注入)
@ServicepublicclassBookServiceImplimplementsBookService{@AutowiredprivateBookDaobookDao;// 按类型自动注入,setter 方法都可以删掉}

原理@Autowired基于暴力反射,可以直接给私有属性赋值。

有多个同类型 Bean 时:@Autowired 会先按类型找,如果找到多个,再根据变量名匹配 bean 名称。若还找不到,就需要配合@Qualifier("bookDao1")指定名称。

注入简单类型 + 读取 properties
@Repository("bookDao")publicclassBookDaoImplimplementsBookDao{@Value("itheima")privateStringname;}

配合@PropertySource读取配置文件:

@Configuration@ComponentScan("com.itheima")@PropertySource("classpath:jdbc.properties")publicclassSpringConfig{}// 使用@Value("${name}")// 对应 jdbc.properties 中的 name=itheima888privateStringname;

四、注解开发管理第三方 Bean

第三方 jar 包里的类我们不能直接加@Component,需要用@Bean注解。

方法:在配置类中写一个方法,返回要管理的对象,并标注@Bean

publicclassJdbcConfig{@BeanpublicDataSourcedataSource(){DruidDataSourceds=newDruidDataSource();ds.setDriverClassName("com.mysql.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/spring_db");ds.setUsername("root");ds.setPassword("root");returnds;}}

引入这个配置类:在主配置类上用@Import(JdbcConfig.class)

@Configuration@ComponentScan("com.itheima")@Import(JdbcConfig.class)publicclassSpringConfig{}

🎯最佳实践:把不同类型的第三方 Bean 分开放到各自的配置类(如JdbcConfigMyBatisConfig),再用@Import统一引入,结构清晰。

为第三方 Bean 注入资源

方法参数中直接写要注入的对象,Spring 会自动装配。

@BeanpublicDataSourcedataSource(BookDaobookDao){// 自动注入 bookDaoSystem.out.println(bookDao);...}

简单类型还是用@Value注入,也可以配合@PropertySource从配置文件读取。


五、XML 配置 vs 注解开发 对照表

功能XML 配置注解开发
定义 bean<bean id="" class="">@Component/@Controller/@Service/@Repository+@ComponentScan
注入依赖(引用)<property name="" ref="">@Autowired+@Qualifier
注入依赖(简单)<property name="" value="">@Value
配置第三方 bean<bean>配合工厂方法@Bean标注在方法上
作用范围scope属性@Scope
生命周期init-method/destroy-method@PostConstruct/@PreDestroy
加载 properties<context:property-placeholder>@PropertySource+@Value("${}")

六、Spring 整合 MyBatis

现在要把 MyBatis 的核心对象也交给 Spring 管,让容器帮我们创建SqlSessionFactory和 Mapper 代理对象。

6.1 整合思路

回顾原生 MyBatis 开发核心对象:

  • SqlSessionFactory需要数据源、配置等环境
  • SqlSessionSqlSessionFactory产生
  • Mapper 接口通过SqlSession.getMapper()获得

Spring 整合后的目标:

  • DataSource→ Spring 管理(Druid)
  • SqlSessionFactory→ Spring 管理(用SqlSessionFactoryBean
  • Mapper 接口 → Spring 通过MapperScannerConfigurer自动扫描并创建代理对象,放入容器

6.2 具体步骤

  1. 引入整合包
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency>
  1. 创建 MyBatis 配置类
publicclassMyBatisConfig{@BeanpublicSqlSessionFactoryBeansqlSessionFactory(DataSourcedataSource){SqlSessionFactoryBeanfactoryBean=newSqlSessionFactoryBean();factoryBean.setDataSource(dataSource);// 数据源factoryBean.setTypeAliasesPackage("com.itheima.domain");// 别名扫描returnfactoryBean;}@BeanpublicMapperScannerConfigurermapperScannerConfigurer(){MapperScannerConfigurerscanner=newMapperScannerConfigurer();scanner.setBasePackage("com.itheima.dao");// Mapper 接口所在包returnscanner;}}
  1. 主配置类引入
@Configuration@ComponentScan("com.itheima")@PropertySource("classpath:jdbc.properties")@Import({JdbcConfig.class,MyBatisConfig.class})publicclassSpringConfig{}

现在就可以直接注入 Service 使用了,完全不用手动操作 MyBatis 的 SqlSession 了。


七、Spring 整合 JUnit

测试类里也可以让 Spring 环境自动开启,通过简单注解就能注入需要的 Bean。

步骤

  1. 引入spring-test依赖
  2. 测试类上添加:
    • @RunWith(SpringJUnit4ClassRunner.class):指定 Spring 的运行器
    • @ContextConfiguration(classes = SpringConfig.class):指定配置类(或locations指定 xml)
  3. 直接@Autowired注入要测试的 Bean,编写@Test方法
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes=SpringConfig.class)publicclassAccountServiceTest{@AutowiredprivateAccountServiceaccountService;@TestpublicvoidtestFindById(){System.out.println(accountService.findById(1));}}

🧪挑战任务:用注解方式重写前两天所有的 XML 配置,再整合 MyBatis 和 JUnit,跑通一个从 Controller 到 Service 到 Dao 再到数据库的全链调用。遇到NoUniqueBeanDefinitionException不要慌,先用@Qualifier指定,再回来优化你的设计。


八、总结

今天我们从 XML 成功过渡到了注解驱动开发,并完成了 Spring 与 MyBatis、JUnit 的整合。核心能力矩阵如下:

技能关键注解/类
定义 Bean@Component,@Service,@Repository,@Configuration+@Bean
包扫描@ComponentScan
依赖注入(引用/简单)@Autowired,@Qualifier,@Value
加载 properties@PropertySource
生命周期/作用范围@PostConstruct,@PreDestroy,@Scope
整合 MyBatisSqlSessionFactoryBean,MapperScannerConfigurer
整合 JUnit@RunWith,@ContextConfiguration

学到这里,你会发现 Spring Boot 的@SpringBootApplication其实就是@Configuration+@ComponentScan+ 一堆自动配置的封装。地基已打牢,后续学习将势如破竹。

🎤结课小调查:今天的内容中,让你感觉最“爽”的点是哪个?
A. 终于不用写 XML 了
B.@Autowired自动注入
C.MapperScannerConfigurer自动扫描 DAO
D. Junit 测试也能用@Autowired

评论区告诉我,看看大家是不是都选了 A!有任何疑问或整合时遇到的错误,也欢迎贴出来,我们一起排查。


本文为 Spring Framework 第三天授课内容整理,至此我们已经完成了 Spring 核心原理与注解开发的学习。下期我们将进入 AOP 的学习,敬请期待!如果觉得有帮助,别忘了点赞、收藏、关注,你的支持是我最大的动力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 22:32:03

ME-AI:封装专家直觉,用机器学习自动化发现拓扑材料新描述符

1. 项目概述&#xff1a;当AI成为材料科学家的“直觉放大器”在材料科学&#xff0c;尤其是凝聚态物理和拓扑材料这个前沿领域&#xff0c;寻找和预测新材料一直是一项极具挑战性的工作。传统的“试错法”不仅成本高昂&#xff0c;而且效率低下。一个经验丰富的材料科学家&…

作者头像 李华
网站建设 2026/5/9 22:30:33

CANN昇腾模型压缩工具包AMCT

AMCT 【免费下载链接】amct AMCT是CANN提供的昇腾AI处理器亲和的模型压缩工具仓。 项目地址: https://gitcode.com/cann/amct &#x1f525;Latest News [2025/4/24] 支持将deepseekv4模型量化为int8。[2025/4/17] 支持HiFloat8分位量化&#xff08;quantile&#xff0…

作者头像 李华
网站建设 2026/5/9 22:30:15

自动驾驶可解释AI:从黑盒模型到透明决策的工程实践

1. 项目概述&#xff1a;当“黑盒”遇上方向盘最近和几个做自动驾驶感知和规控的朋友聊天&#xff0c;大家不约而同地提到了一个共同的焦虑&#xff1a;模型越来越准&#xff0c;但心里越来越没底。这感觉就像你请了一位驾驶技术出神入化的老司机&#xff0c;但他从不告诉你为什…

作者头像 李华
网站建设 2026/5/9 22:26:34

10分钟自动化部署OpenClaw AI助手:基于Ubuntu VPS的完整实践指南

1. 项目概述&#xff1a;一键部署你的专属AI助手 如果你和我一样&#xff0c;对AI Agent&#xff08;智能体&#xff09;的潜力感到兴奋&#xff0c;但又对在服务器上手动配置、安装、调试的繁琐过程感到头疼&#xff0c;那么这个项目就是为你准备的。 ortegarod/openclaw-vp…

作者头像 李华
网站建设 2026/5/9 22:21:32

CANN/cann-samples MoE通信优化实践

moe dispatch 和 combine 通信算子性能优化实践与效果分析 【免费下载链接】cann-samples 算子领域高性能实战演进样例与体系化调优知识库 项目地址: https://gitcode.com/cann/cann-samples 背景介绍 在大模型训练与推理中&#xff0c;MoE&#xff08;Mixture-of-Expe…

作者头像 李华
网站建设 2026/5/9 22:16:09

CANN Qwen3-next推理优化

NPU Qwen3-next推理优化实践 【免费下载链接】cann-recipes-infer 本项目针对LLM与多模态模型推理业务中的典型模型、加速算法&#xff0c;提供基于CANN平台的优化样例 项目地址: https://gitcode.com/cann/cann-recipes-infer 阿里千问团队发布了 Qwen3-Next 模型&…

作者头像 李华