前言前面两天我们用 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 容器。步骤导入依赖dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.16/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency在applicationContext.xml中配置 Bean注入数据库四要素beaniddataSourceclasscom.alibaba.druid.pool.DruidDataSourcepropertynamedriverClassNamevaluecom.mysql.jdbc.Driver/propertynameurlvaluejdbc:mysql://localhost:3306/spring_db/propertynameusernamevalueroot/propertynamepasswordvalueroot//bean从容器获取并打印DataSourcedataSource(DataSource)ctx.getBean(dataSource);System.out.println(dataSource);动手尝试换成 C3P0 试试管理它的类是ComboPooledDataSource注意属性名不一样driverClass,jdbcUrl等。你会发现 C3P0 初始化就要求驱动需要额外引入mysql-connector-java。1.2 加载 properties 文件把数据库连接信息硬编码在 XML 里不利于维护咱们把它提到jdbc.properties里。步骤创建jdbc.propertiesjdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://127.0.0.1:3306/spring_db jdbc.usernameroot jdbc.passwordroot在 XML 中开启context命名空间并加载文件beans...xmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocation... spring-context.xsd!-- 加载 propertiessystem-properties-modeNEVER 防止系统环境变量覆盖 --context:property-placeholderlocationjdbc.propertiessystem-properties-modeNEVER//beans用${key}引用值propertynamedriverClassNamevalue${jdbc.driver}/propertynameurlvalue${jdbc.url}/propertynameusernamevalue${jdbc.username}/propertynamepasswordvalue${jdbc.password}/多个配置文件加载方式!-- 方式一用逗号分隔 --context:property-placeholderlocationjdbc.properties,jdbc2.properties/!-- 方式二通配符 *.properties不建议 --!-- 方式三标准写法classpath: 开头 --context:property-placeholderlocationclasspath:*.properties/⚠️注意username这个 key 会跟系统环境变量冲突最好用jdbc.username这类带前缀的名字或加上system-properties-modeNEVER。二、核心容器我们已经用过ApplicationContext这里系统梳理一下容器的创建和获取 Bean 的方式。2.1 容器的创建方式推荐ClassPathXmlApplicationContext(applicationContext.xml)– 从类路径加载了解FileSystemXmlApplicationContext(绝对路径)– 从文件系统加载路径写死不推荐2.2 获取 Bean 的三种方式// 方式1按名称需要强转BookDaobookDao(BookDao)ctx.getBean(bookDao);// 方式2按名称 类型省去强转BookDaobookDaoctx.getBean(bookDao,BookDao.class);// 方式3按类型容器中该类型 Bean 必须唯一BookDaobookDaoctx.getBean(BookDao.class);2.3 容器层次与 BeanFactoryBeanFactoryIoC 容器的顶层接口延迟加载获取 bean 时才创建ApplicationContext是BeanFactory的子接口立即加载初始化容器时就创建所有单例 bean若想让ApplicationContext也延迟加载某个 bean可在配置中加lazy-inittrue。小结日常开发多采用ClassPathXmlApplicationContext和按类型获取 bean 的方式。三、IOC/DI 注解开发终于不用写 XML 里的bean了Spring 提供了几个注解帮我们自动注册 Bean。3.1 注解定义 Bean在类上添加Component(bookDao)相当于bean idbookDao class...在 xml 中配置包扫描让 Spring 能发现这些注解context:component-scanbase-packagecom.itheima/以后直接在类上写注解即可。常用分层注解功能同Component只是语义更明确Controller表现层Service业务层Repository数据层如果不指定名称默认是类名首字母小写。3.2 纯注解开发告别 XML用配置类完全替代 XML。Configuration// 标志这是一个配置类相当于 applicationContext.xmlComponentScan(com.itheima)// 包扫描publicclassSpringConfig{}启动容器改用ApplicationContextctxnewAnnotationConfigApplicationContext(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)指定名称。注入简单类型 读取 propertiesRepository(bookDao)publicclassBookDaoImplimplementsBookDao{Value(itheima)privateStringname;}配合PropertySource读取配置文件ConfigurationComponentScan(com.itheima)PropertySource(classpath:jdbc.properties)publicclassSpringConfig{}// 使用Value(${name})// 对应 jdbc.properties 中的 nameitheima888privateStringname;四、注解开发管理第三方 Bean第三方 jar 包里的类我们不能直接加Component需要用Bean注解。方法在配置类中写一个方法返回要管理的对象并标注Bean。publicclassJdbcConfig{BeanpublicDataSourcedataSource(){DruidDataSourcedsnewDruidDataSource();ds.setDriverClassName(com.mysql.jdbc.Driver);ds.setUrl(jdbc:mysql://localhost:3306/spring_db);ds.setUsername(root);ds.setPassword(root);returnds;}}引入这个配置类在主配置类上用Import(JdbcConfig.class)。ConfigurationComponentScan(com.itheima)Import(JdbcConfig.class)publicclassSpringConfig{}最佳实践把不同类型的第三方 Bean 分开放到各自的配置类如JdbcConfig、MyBatisConfig再用Import统一引入结构清晰。为第三方 Bean 注入资源方法参数中直接写要注入的对象Spring 会自动装配。BeanpublicDataSourcedataSource(BookDaobookDao){// 自动注入 bookDaoSystem.out.println(bookDao);...}简单类型还是用Value注入也可以配合PropertySource从配置文件读取。五、XML 配置 vs 注解开发 对照表功能XML 配置注解开发定义 beanbean id classComponent/Controller/Service/RepositoryComponentScan注入依赖引用property name refAutowiredQualifier注入依赖简单property name valueValue配置第三方 beanbean配合工厂方法Bean标注在方法上作用范围scope属性Scope生命周期init-method/destroy-methodPostConstruct/PreDestroy加载 propertiescontext:property-placeholderPropertySourceValue(${})六、Spring 整合 MyBatis现在要把 MyBatis 的核心对象也交给 Spring 管让容器帮我们创建SqlSessionFactory和 Mapper 代理对象。6.1 整合思路回顾原生 MyBatis 开发核心对象SqlSessionFactory需要数据源、配置等环境SqlSession由SqlSessionFactory产生Mapper 接口通过SqlSession.getMapper()获得Spring 整合后的目标DataSource→ Spring 管理DruidSqlSessionFactory→ Spring 管理用SqlSessionFactoryBeanMapper 接口 → Spring 通过MapperScannerConfigurer自动扫描并创建代理对象放入容器6.2 具体步骤引入整合包dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.2.10.RELEASE/version/dependencydependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion1.3.0/version/dependency创建 MyBatis 配置类publicclassMyBatisConfig{BeanpublicSqlSessionFactoryBeansqlSessionFactory(DataSourcedataSource){SqlSessionFactoryBeanfactoryBeannewSqlSessionFactoryBean();factoryBean.setDataSource(dataSource);// 数据源factoryBean.setTypeAliasesPackage(com.itheima.domain);// 别名扫描returnfactoryBean;}BeanpublicMapperScannerConfigurermapperScannerConfigurer(){MapperScannerConfigurerscannernewMapperScannerConfigurer();scanner.setBasePackage(com.itheima.dao);// Mapper 接口所在包returnscanner;}}主配置类引入ConfigurationComponentScan(com.itheima)PropertySource(classpath:jdbc.properties)Import({JdbcConfig.class,MyBatisConfig.class})publicclassSpringConfig{}现在就可以直接注入 Service 使用了完全不用手动操作 MyBatis 的 SqlSession 了。七、Spring 整合 JUnit测试类里也可以让 Spring 环境自动开启通过简单注解就能注入需要的 Bean。步骤引入spring-test依赖测试类上添加RunWith(SpringJUnit4ClassRunner.class)指定 Spring 的运行器ContextConfiguration(classes SpringConfig.class)指定配置类或locations指定 xml直接Autowired注入要测试的 Bean编写Test方法RunWith(SpringJUnit4ClassRunner.class)ContextConfiguration(classesSpringConfig.class)publicclassAccountServiceTest{AutowiredprivateAccountServiceaccountService;TestpublicvoidtestFindById(){System.out.println(accountService.findById(1));}}挑战任务用注解方式重写前两天所有的 XML 配置再整合 MyBatis 和 JUnit跑通一个从 Controller 到 Service 到 Dao 再到数据库的全链调用。遇到NoUniqueBeanDefinitionException不要慌先用Qualifier指定再回来优化你的设计。八、总结今天我们从 XML 成功过渡到了注解驱动开发并完成了 Spring 与 MyBatis、JUnit 的整合。核心能力矩阵如下技能关键注解/类定义 BeanComponent,Service,Repository,ConfigurationBean包扫描ComponentScan依赖注入引用/简单Autowired,Qualifier,Value加载 propertiesPropertySource生命周期/作用范围PostConstruct,PreDestroy,Scope整合 MyBatisSqlSessionFactoryBean,MapperScannerConfigurer整合 JUnitRunWith,ContextConfiguration学到这里你会发现 Spring Boot 的SpringBootApplication其实就是ConfigurationComponentScan 一堆自动配置的封装。地基已打牢后续学习将势如破竹。结课小调查今天的内容中让你感觉最“爽”的点是哪个A. 终于不用写 XML 了B.Autowired自动注入C.MapperScannerConfigurer自动扫描 DAOD. Junit 测试也能用Autowired评论区告诉我看看大家是不是都选了 A有任何疑问或整合时遇到的错误也欢迎贴出来我们一起排查。本文为 Spring Framework 第三天授课内容整理至此我们已经完成了 Spring 核心原理与注解开发的学习。下期我们将进入 AOP 的学习敬请期待如果觉得有帮助别忘了点赞、收藏、关注你的支持是我最大的动力。
Spring 第三天:注解驱动开发与整合 MyBatis/JUnit
发布时间:2026/6/27 16:23:57
前言前面两天我们用 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 容器。步骤导入依赖dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.16/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency在applicationContext.xml中配置 Bean注入数据库四要素beaniddataSourceclasscom.alibaba.druid.pool.DruidDataSourcepropertynamedriverClassNamevaluecom.mysql.jdbc.Driver/propertynameurlvaluejdbc:mysql://localhost:3306/spring_db/propertynameusernamevalueroot/propertynamepasswordvalueroot//bean从容器获取并打印DataSourcedataSource(DataSource)ctx.getBean(dataSource);System.out.println(dataSource);动手尝试换成 C3P0 试试管理它的类是ComboPooledDataSource注意属性名不一样driverClass,jdbcUrl等。你会发现 C3P0 初始化就要求驱动需要额外引入mysql-connector-java。1.2 加载 properties 文件把数据库连接信息硬编码在 XML 里不利于维护咱们把它提到jdbc.properties里。步骤创建jdbc.propertiesjdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://127.0.0.1:3306/spring_db jdbc.usernameroot jdbc.passwordroot在 XML 中开启context命名空间并加载文件beans...xmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocation... spring-context.xsd!-- 加载 propertiessystem-properties-modeNEVER 防止系统环境变量覆盖 --context:property-placeholderlocationjdbc.propertiessystem-properties-modeNEVER//beans用${key}引用值propertynamedriverClassNamevalue${jdbc.driver}/propertynameurlvalue${jdbc.url}/propertynameusernamevalue${jdbc.username}/propertynamepasswordvalue${jdbc.password}/多个配置文件加载方式!-- 方式一用逗号分隔 --context:property-placeholderlocationjdbc.properties,jdbc2.properties/!-- 方式二通配符 *.properties不建议 --!-- 方式三标准写法classpath: 开头 --context:property-placeholderlocationclasspath:*.properties/⚠️注意username这个 key 会跟系统环境变量冲突最好用jdbc.username这类带前缀的名字或加上system-properties-modeNEVER。二、核心容器我们已经用过ApplicationContext这里系统梳理一下容器的创建和获取 Bean 的方式。2.1 容器的创建方式推荐ClassPathXmlApplicationContext(applicationContext.xml)– 从类路径加载了解FileSystemXmlApplicationContext(绝对路径)– 从文件系统加载路径写死不推荐2.2 获取 Bean 的三种方式// 方式1按名称需要强转BookDaobookDao(BookDao)ctx.getBean(bookDao);// 方式2按名称 类型省去强转BookDaobookDaoctx.getBean(bookDao,BookDao.class);// 方式3按类型容器中该类型 Bean 必须唯一BookDaobookDaoctx.getBean(BookDao.class);2.3 容器层次与 BeanFactoryBeanFactoryIoC 容器的顶层接口延迟加载获取 bean 时才创建ApplicationContext是BeanFactory的子接口立即加载初始化容器时就创建所有单例 bean若想让ApplicationContext也延迟加载某个 bean可在配置中加lazy-inittrue。小结日常开发多采用ClassPathXmlApplicationContext和按类型获取 bean 的方式。三、IOC/DI 注解开发终于不用写 XML 里的bean了Spring 提供了几个注解帮我们自动注册 Bean。3.1 注解定义 Bean在类上添加Component(bookDao)相当于bean idbookDao class...在 xml 中配置包扫描让 Spring 能发现这些注解context:component-scanbase-packagecom.itheima/以后直接在类上写注解即可。常用分层注解功能同Component只是语义更明确Controller表现层Service业务层Repository数据层如果不指定名称默认是类名首字母小写。3.2 纯注解开发告别 XML用配置类完全替代 XML。Configuration// 标志这是一个配置类相当于 applicationContext.xmlComponentScan(com.itheima)// 包扫描publicclassSpringConfig{}启动容器改用ApplicationContextctxnewAnnotationConfigApplicationContext(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)指定名称。注入简单类型 读取 propertiesRepository(bookDao)publicclassBookDaoImplimplementsBookDao{Value(itheima)privateStringname;}配合PropertySource读取配置文件ConfigurationComponentScan(com.itheima)PropertySource(classpath:jdbc.properties)publicclassSpringConfig{}// 使用Value(${name})// 对应 jdbc.properties 中的 nameitheima888privateStringname;四、注解开发管理第三方 Bean第三方 jar 包里的类我们不能直接加Component需要用Bean注解。方法在配置类中写一个方法返回要管理的对象并标注Bean。publicclassJdbcConfig{BeanpublicDataSourcedataSource(){DruidDataSourcedsnewDruidDataSource();ds.setDriverClassName(com.mysql.jdbc.Driver);ds.setUrl(jdbc:mysql://localhost:3306/spring_db);ds.setUsername(root);ds.setPassword(root);returnds;}}引入这个配置类在主配置类上用Import(JdbcConfig.class)。ConfigurationComponentScan(com.itheima)Import(JdbcConfig.class)publicclassSpringConfig{}最佳实践把不同类型的第三方 Bean 分开放到各自的配置类如JdbcConfig、MyBatisConfig再用Import统一引入结构清晰。为第三方 Bean 注入资源方法参数中直接写要注入的对象Spring 会自动装配。BeanpublicDataSourcedataSource(BookDaobookDao){// 自动注入 bookDaoSystem.out.println(bookDao);...}简单类型还是用Value注入也可以配合PropertySource从配置文件读取。五、XML 配置 vs 注解开发 对照表功能XML 配置注解开发定义 beanbean id classComponent/Controller/Service/RepositoryComponentScan注入依赖引用property name refAutowiredQualifier注入依赖简单property name valueValue配置第三方 beanbean配合工厂方法Bean标注在方法上作用范围scope属性Scope生命周期init-method/destroy-methodPostConstruct/PreDestroy加载 propertiescontext:property-placeholderPropertySourceValue(${})六、Spring 整合 MyBatis现在要把 MyBatis 的核心对象也交给 Spring 管让容器帮我们创建SqlSessionFactory和 Mapper 代理对象。6.1 整合思路回顾原生 MyBatis 开发核心对象SqlSessionFactory需要数据源、配置等环境SqlSession由SqlSessionFactory产生Mapper 接口通过SqlSession.getMapper()获得Spring 整合后的目标DataSource→ Spring 管理DruidSqlSessionFactory→ Spring 管理用SqlSessionFactoryBeanMapper 接口 → Spring 通过MapperScannerConfigurer自动扫描并创建代理对象放入容器6.2 具体步骤引入整合包dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.2.10.RELEASE/version/dependencydependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion1.3.0/version/dependency创建 MyBatis 配置类publicclassMyBatisConfig{BeanpublicSqlSessionFactoryBeansqlSessionFactory(DataSourcedataSource){SqlSessionFactoryBeanfactoryBeannewSqlSessionFactoryBean();factoryBean.setDataSource(dataSource);// 数据源factoryBean.setTypeAliasesPackage(com.itheima.domain);// 别名扫描returnfactoryBean;}BeanpublicMapperScannerConfigurermapperScannerConfigurer(){MapperScannerConfigurerscannernewMapperScannerConfigurer();scanner.setBasePackage(com.itheima.dao);// Mapper 接口所在包returnscanner;}}主配置类引入ConfigurationComponentScan(com.itheima)PropertySource(classpath:jdbc.properties)Import({JdbcConfig.class,MyBatisConfig.class})publicclassSpringConfig{}现在就可以直接注入 Service 使用了完全不用手动操作 MyBatis 的 SqlSession 了。七、Spring 整合 JUnit测试类里也可以让 Spring 环境自动开启通过简单注解就能注入需要的 Bean。步骤引入spring-test依赖测试类上添加RunWith(SpringJUnit4ClassRunner.class)指定 Spring 的运行器ContextConfiguration(classes SpringConfig.class)指定配置类或locations指定 xml直接Autowired注入要测试的 Bean编写Test方法RunWith(SpringJUnit4ClassRunner.class)ContextConfiguration(classesSpringConfig.class)publicclassAccountServiceTest{AutowiredprivateAccountServiceaccountService;TestpublicvoidtestFindById(){System.out.println(accountService.findById(1));}}挑战任务用注解方式重写前两天所有的 XML 配置再整合 MyBatis 和 JUnit跑通一个从 Controller 到 Service 到 Dao 再到数据库的全链调用。遇到NoUniqueBeanDefinitionException不要慌先用Qualifier指定再回来优化你的设计。八、总结今天我们从 XML 成功过渡到了注解驱动开发并完成了 Spring 与 MyBatis、JUnit 的整合。核心能力矩阵如下技能关键注解/类定义 BeanComponent,Service,Repository,ConfigurationBean包扫描ComponentScan依赖注入引用/简单Autowired,Qualifier,Value加载 propertiesPropertySource生命周期/作用范围PostConstruct,PreDestroy,Scope整合 MyBatisSqlSessionFactoryBean,MapperScannerConfigurer整合 JUnitRunWith,ContextConfiguration学到这里你会发现 Spring Boot 的SpringBootApplication其实就是ConfigurationComponentScan 一堆自动配置的封装。地基已打牢后续学习将势如破竹。结课小调查今天的内容中让你感觉最“爽”的点是哪个A. 终于不用写 XML 了B.Autowired自动注入C.MapperScannerConfigurer自动扫描 DAOD. Junit 测试也能用Autowired评论区告诉我看看大家是不是都选了 A有任何疑问或整合时遇到的错误也欢迎贴出来我们一起排查。本文为 Spring Framework 第三天授课内容整理至此我们已经完成了 Spring 核心原理与注解开发的学习。下期我们将进入 AOP 的学习敬请期待如果觉得有帮助别忘了点赞、收藏、关注你的支持是我最大的动力。