1 Spring 概述
Spring 版本历史(参考 wiki-Version history):
Version | Date | Notes |
---|---|---|
0.9 | 2003 | |
1.0 | March 24, 2004 | First production release. |
2.0 | 2006 | |
3.0 | 2009 | |
4.0 | 2013 | |
5.0 | 2017 |
目前(2021-10-5) Spring Framework 的最新 GA(general availability) 版本是 5.3.10.
第一阶段: xml 配置
在 Spring 1.x 时代, 都是使用 xml 配置 Bean.
第二阶段: 注解配置
在 Spring 2.x 时代, 随着 JDK 1.5 支持注解, Spring 提供了 声明 Bean 的注解, 大大减少了配置工作量.
第三阶段: Java 配置
从 Spring 3.x 到现在, Spring 提供了 Java 配置的能力. Spring 推荐使用 Java 配置.
Spring 中的核心概念:
- Bean: 每一个被 Spring 管理的 Java 对象称之为 Bean.
- 依赖注入 (Dependency Injection, DI): 依赖注入可以把一个对象 注入(组合) 到另一个对象中.
- 控制反转 (Inversion of Control, IoC): Spring IoC 容器负责初始化 Bean, 管理对象间的依赖. 所谓控制反转, 就是把 Java 对象交给 Spring IoC 容器 管理而不是传统的调用者.
- 面向切面编程 (Aspect-Oriented Programming, AOP): 主要目的是解耦. AOP 可以让一组类共享相同的行为.
2 依赖注入
声明 Bean 的注解:
@Component
没有明确的角色.@Service
, 在业务逻辑层 (service 层) 使用.@Repository
, 在数据访问层( dao 层) 使用.@Controller
, 在控制层使用.
注入 Bean 的注解:
@Autowired
: Spring 提供, 我将其翻译成 自动连线…@Inject
: JSR-330 提供.@Resource
: JSR-250 提供.
3 Java 配置
Java 配置是 Spring 4.x 推荐的配置方式, 可以完全替代 xml 配置.
Java 配置也是 Spring Boot 推荐的配置方式.
Java 配置 通过 @Configuration
和 @Bean
来实现.
@Configuration
是一个类注解, 声明当前类是一个配置类. 相当于 Spring 配置的 xml 文件.@Bean
是一个方法注解, 声明当前方法的返回值为 一个 Bean.
在 依赖配置 小节 介绍了 4 种依赖注入的方法 @Component
, @Service
, @Repository
和 @Controller
. 这 4 种都是 注解配置.
一般来说,
在全局配置时(比如 数据库配置, MVC 相关的配置) 使用 Java 配置;
在业务 Bean 配置时使用 注解配置.
4 Hello World 示例
完整代码 在 GitHub 上, 这里只展示部分主要代码片段.
编写一个 功能类(做业务逻辑处理) 的 Bean:
// 使用 @Service 注解声明当前类为 Spring 管理的一个 Bean.
// 这里使用 @Component, @Service, @Repository 和 Controller 是等效的,
// 可以根据需要选用
@Service
public class FunctionService {
public String sayHello(String name) {
return "Hello " + name;
}
}
编写一个调用 上面的 功能类 的 Bean:
// 注解声明当前类为 Spring 管理的一个 Bean
@Service
public class FunctionServiceUser {
// 使用 @Autowired 将 FunctionService 注入到 FunctionServiceUser 中,
// 此处使用 @Inject 或 @Resource 是等效的.
@Autowired
FunctionService functionService;
public String sayHello(String name) {
return functionService.sayHello(name);
}
}
配置类:
// @Configuration 声明当前类是一个配置类
@Configuration
// @ComponentScan 自动扫描包下 所有使用 @Service,
// @Component, @Repository, @Controller 的类,
// 并将它们注册为 Bean.
@ComponentScan("cn.mitrecx.ch1.di")
public class DiConfig {
}
注意到 cn.mitrecx.ch1.di
这个包路径, 我的代码目录结构如下图:
程序入口:
public class MyApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(DiConfig.class);
FunctionServiceUser fsu = context.getBean(FunctionServiceUser.class);
System.out.println(fsu.sayHello("Rosie"));
context.close();
}
}
编译, 执行:
✗ mvn clean package
✗ java -jar target/helloworld-1.0-SNAPSHOT.jar
执行结果:
Oct 05, 2021 6:40:39 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@312b1dae: startup date [Tue Oct 05 18:40:39 CST 2021]; root of context hierarchy
Hello Rosie
Oct 05, 2021 6:40:40 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@312b1dae: startup date [Tue Oct 05 18:40:39 CST 2021]; root of context hierarchy
可以看到第 3 行正确输出了结果.
Reference
[1]. Spring Boot 实战 - 汪云飞