引言
在Spring框架中,IOC(控制反转)和DI(依赖注入)是核心思想。通过注解开发,我们可以大幅简化Spring配置,提高开发效率。本文将深入探讨Spring IOC/DI的注解开发模式,并结合实际案例展示如何管理第三方框架(如Mybatis和Junit)。
一、管理第三方Bean
为避免硬编码,将数据库配置提取到properties文件:
# jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=root
(一)Durid
pom.xml中添加依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
在applicationContext.xml配置文件中添加DruidDataSource的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--管理DruidDataSource对象-->
<bean class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
- driverClassName:数据库驱动
- url:数据库连接地址
- username:数据库连接用户名
- password:数据库连接密码
setter注入数据库连接的四要素,要和自己使用的数据库信息一致。
(二)C3P0
pom.xml中添加依赖
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
- Druid和C3P0在没有导入mysql驱动包的前提下,一个没报错一个报错,说明Druid在初始化的 时候没有去加载驱动,而C3P0刚好相反
- Druid程序运行虽然没有报错,但是当调用DruidDataSource的getConnection()方法获取连 接的时候,也会报找不到驱动类的错误
配置第三方bean,通过setter方法注入ComboPooledDataSource
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
<property name="maxPoolSize" value="1000"/>
</bean>
(三)总结
完成durid或C3P0后,从IOC容器中获取对应的bean对象,之后即可运行程序
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource);
}
}
Druid vs C3P0 对比:
特性 | Druid | C3P0 |
---|---|---|
提供方 | 阿里 | 开源JDBC连接池 |
性能 | 高 | 较低 |
驱动加载时机 | 延迟加载(运行时) | 初始化时加载 |
监控功能 | 强大的监控和统计功能 | 基本功能 |
二、加载Properties配置文件
Spring配置加载
<context:property-placeholder
location="classpath:jdbc.properties"
system-properties-mode="NEVER"/>
加载方式对比
单个文件:
location="jdbc.properties"
多个文件:
location="jdbc.properties,jdbc2.properties"
通配符:
location="*.properties"
类路径:
location="classpath:*.properties"
类路径(含依赖):
location="classpath*:*.properties"
三、Spring核心容器
这里所说的核心容器,可以把它简单的理解为ApplicationContext。
(一)容器创建
传统 XML 配置容器
// 类路径加载(推荐)
ApplicationContext ctx =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 文件系统加载(不推荐使用,当项目的位置发生变化后,代码也需要跟着改,耦合度较高)
ApplicationContext ctx =
new FileSystemXmlApplicationContext("D:/config/applicationContext.xml");
现代注解配置容器
AnnotationConfigApplicationContext是现代 Spring 应用开发中纯注解配置方式的核心入口,完全取代了传统的 XML 配置方式。
// 加载配置类初始化容器
ApplicationContext ctx =
new AnnotationConfigApplicationContext(SpringConfig.class);
- ClassPathXmlApplicationContext是加载XML配置文件
- AnnotationConfigApplicationContext是加载配置类
(二)获取Bean的三种方式
// 1. 按名称获取(需强转)
BookDao dao = (BookDao) ctx.getBean("bookDao");
// 2. 按名称+类型获取(解决强转,但多一个参数)
BookDao dao = ctx.getBean("bookDao", BookDao.class);
// 3. 按类型获取(需确保IOC容器中该类型对应的bean对象只能有一个)
BookDao dao = ctx.getBean(BookDao.class);
(三)容器类层次结构

只需要知晓容器的最上级的父接口为BeanFactory即可
(四)BeanFactory
特性 | BeanFactory | ApplicationContext |
---|---|---|
加载时机 | 延迟加载(使用时创建) | 立即加载(启动时创建) |
功能完整性 | 基础功能 | 扩展功能(AOP等) |
使用场景 | 资源受限环境 | 大多数应用场景 |
(五)小结
- BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
- ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
- ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
- ApplicationContext接口常用初始化类
- ClassPathXmlApplicationContext(常用)
- FileSystemXmlApplicationContext
四、注解开发
(一)核心注解
特性 | @Component | @Controller | @Service | @Repository |
---|---|---|---|---|
继承关系 | 基础注解 | 派生自@Component | 派生自@Component | 派生自@Component |
使用场景 | 通用组件 | MVC控制器 | 业务逻辑层 | 数据访问层 |
语义含义 | 通用Spring组件 | 处理用户请求 | 业务逻辑服务 | 数据存储库 |
特殊功能 | 无 | 处理HTTP请求 | 事务管理 | 异常转换 |
层级位置 | 任意层 | 表现层 | 业务层 | 持久层 |
典型用途 | 工具类、配置类 | REST控制器 | 业务逻辑实现 | DAO实现类 |
虽然技术上可以全部使用@Component
,但使用特定注解有利于明确标识组件在架构中的角色,提高代码可读性,方便针对特定层进行切面编程,以及进行如@Repository
的异常转换功能。
处理HTTP请求 →
@Controller
- 系统的"门面",处理用户交互实现业务逻辑 →
@Service
- 业务逻辑的"大脑",实现核心功能数据库访问 →
@Repository
- 数据访问的"手",与持久化存储交互通用工具类 →
@Component
- 通用的"工具",提供辅助功能
(二)纯注解配置
@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:app.properties")
public class AppConfig {
}
特性 | @Configuration | @ComponentScan |
---|---|---|
主要作用 | 标识配置类 | 自动扫描并注册组件 |
替代方案 | XML配置文件 (<beans> 标签) | XML组件扫描 (<context:component-scan> ) |
使用位置 | 类级别 | 类级别(常与@Configuration一起使用) |
核心功能 | 定义Bean和配置 | 发现和管理组件 |
是否必须 | 纯注解开发必须 | 可选,但强烈推荐使用 |
典型使用场景 | 定义第三方Bean、全局配置 | 自动注册业务组件 |
- ,@Configuration设置该类为spring配置类,使用类替换applicationContext.xml文件
- value(默认):定义bean的id
- @ComponentScan设置spring配置类扫描路径,用于加载使用注解格式定义的bean
- value(默认):扫描路径,此路径可以逐层向下扫描
此注解只能添加一次,多个数据请用数组格式@ComponentScan({com.example.service","com.example.dao"})
(三)Bean作用域与生命周期
@Repository
@Scope("prototype") // 默认为singleton
public class UserDaoImpl {
@PostConstruct // 设置该方法为初始化方法
public void init() {
System.out.println("Bean初始化");
}
@PreDestroy // 设置该方法为销毁方法
public void destroy() {
System.out.println("Bean销毁");
}
}
名称
|
@Scope
|
类型
|
类注解
|
位置
|
类定义上方
|
作用
|
设置该类创建对象的作用范围
可用于设置创建出的bean是否为单例对象
|
属性
|
value(默认):定义bean作用范围,
默认值singleton(单例),可选值prototype(非单例)
|
xml属性与注解的关系大致如下:
(四)依赖注入
@Service
public class UserServiceImpl {
@Autowired // 按类型注入
private UserDao userDao;
@Autowired
@Qualifier("mainDataSource") // 按名称注入
private DataSource dataSource;
@Value("${app.timeout}") // 注入简单值
private int timeout;
}
注解名称 | 类型 | 应用位置 | 主要作用 | 关键属性 |
---|---|---|---|---|
@Autowired | 属性/方法/方法形参注解 | 属性定义上方 setter方法上方 方法形参前面 | 自动装配引用类型 根据类型自动注入依赖对象 | required :是否必须注入(true/false,默认true) |
@Qualifier | 属性/方法注解 | 属性定义上方 setter方法上方 | 精确指定Bean名称 解决同类型多个Bean的歧义 | value :指定要注入的Bean ID |
@Value | 属性/方法注解 | 属性定义上方 setter方法上方 | 注入简单类型值 注入基本类型、字符串或表达式结果 | value :要注入的值或表达式(如 ${property} ) |
@PropertySource | 类注解 | 类定义上方 | 加载外部配置 将properties文件加载到Spring环境 | value :配置文件名或数组(支持 classpath: 前缀) |
五、整合第三方框架
(一) 管理第三方Bean
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
// 其他配置...
return ds;
}
}
(二)整合Mybatis
@Configuration
public class MybatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setTypeAliasesPackage("com.example.domain");
return factory.getObject();
}
}
(三)整合Junit
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppConfig.class})
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testFindUser() {
User user = userService.findById(1);
assertNotNull(user);
}
}
注解 | 应用位置 | 主要作用 | 关键属性 | 适用场景 |
---|---|---|---|---|
@Bean | 配置类中的方法上 | 显式声明 Spring Bean 将方法返回对象注册为 Spring Bean | name/value :Bean 名称initMethod :初始化方法destroyMethod :销毁方法 | 管理第三方库组件 复杂初始化逻辑 条件化创建 Bean |
@Import | 配置类上 | 模块化配置组合 导入其他配置类或组件 | value :要导入的类数组(支持配置类、组件类、ImportSelector 等) | 大型应用配置拆分 特性模块化 自动配置机制 |
@RunWith | JUnit 测试类上 | 指定测试运行器 定制测试执行环境 | value :测试运行器类(如 SpringJUnit4ClassRunner ) | Spring 集成测试 需要容器环境的测试 定制测试行为 |
@Context Configuration | JUnit 测试类上 | 加载 Spring 配置 为测试提供应用上下文 | classes :配置类数组locations :配置文件路径inheritLocations :继承配置 | 单元测试依赖注入 集成测试环境 多配置组合测试 |
六、总结
功能 | XML配置 | 注解 |
---|---|---|
定义Bean | <bean> | @Component 及其衍生 |
作用域 | scope 属性 | @Scope |
生命周期 | init-method/destroy | @PostConstruct/@PreDestroy |
依赖注入 | <property> | @Autowired/@Value |
第三方Bean管理 | <bean> | @Bean |
配置文件加载 | <context:property-placeholder> | @PropertySource |