文章目录
1.1 IoC容器:Spring的智能管家
想象一下,你是一家大公司的CEO,而Spring IoC容器就是你的私人智能管家。传统开发中,你需要自己记住每个员工的联系方式,自己安排会议,自己协调资源——这就像在代码中频繁使用new
关键字创建对象:
// 没有管家的苦日子
Employee developer = new Developer();
Employee manager = new Manager();
Project project = new Project(developer, manager);
而有了Spring这位智能管家,你只需要告诉他:“我需要一个项目经理”,管家就会自动找到最合适的人选并送到你面前:
// 有管家的幸福生活
@Autowired
private Project project; // 管家,帮我组建一个项目团队!
源码视角:
Spring的核心容器是ApplicationContext
接口,它的默认实现AnnotationConfigApplicationContext
就是专门处理注解的智能管家:
// 启动Spring容器(聘请管家)
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 向管家索取需要的服务
ProjectService projectService = context.getBean(ProjectService.class);
1.2 注解驱动:给管家下指令
在Spring Boot中,我们主要通过注解来指导管家工作。这些注解就像给管家的工作指令:
1.2.1 @SpringBootApplication:总管家的聘书
这是Spring Boot应用的起点注解,它实际上是一个组合注解:
@SpringBootApplication // ← 这就是聘书,包含三个重要指令
public class CompanyApplication {
public static void main(String[] args) {
SpringApplication.run(CompanyApplication.class, args); // 正式聘请管家
}
}
拆解这个"聘书",包含三个核心指令:
@SpringBootConfiguration // ← 指令1:这是家正规公司(配置类)
@EnableAutoConfiguration // ← 指令2:管家可以自主决策(自动配置)
@ComponentScan // ← 指令3:在公司内寻找人才(组件扫描)
public class CompanyApplication {
// ...
}
1.2.2 组件注解:员工的身份标识
在公司里,不同类型的员工有不同的工牌:
@Component // ← 普通员工工牌
public class Developer {
public void code() {
System.out.println("编写代码...");
}
}
@Service // ← 管理层工牌(特殊待遇)
public class ProjectService {
private final Developer developer;
public ProjectService(Developer developer) {
this.developer = developer;
}
}
@Repository // ← 仓库管理员工牌(有错误转换特权)
public class ProjectRepository {
// 数据访问逻辑
}
@Controller // ← 前台接待员工牌(处理外部请求)
public class ProjectController {
private final ProjectService projectService;
public ProjectController(ProjectService projectService) {
this.projectService = projectService;
}
}
源码洞察:
这些注解都被元注解@Component
标记,意味着它们都会被组件扫描发现:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // 所有注解都是@Component的特殊化
public @interface Service {
// ...
}
1.2.3 @Autowired:依赖注入的三种方式
告诉管家如何给员工配备助手和设备:
@Service
public class ProjectService {
// 方式1:字段注入(直接配助手)- 简单但不推荐
@Autowired
private Developer developer;
// 方式2:构造器注入(招聘时指定助手)- 推荐方式
private final Designer designer;
@Autowired
public ProjectService(Designer designer) {
this.designer = designer; // 一旦配备,不可更改
}
// 方式3:Setter注入(后期配置设备)- 可选依赖
private Printer printer;
@Autowired
public void setPrinter(Printer printer) {
this.printer = printer; // 可以后期更换
}
}
最佳实践:使用构造器注入,就像在招聘时就确定团队组成,这样团队更稳定。
1.2.4 @Bean注解:手动招聘特殊人才
有些特殊人才(第三方库的类)没有Spring的工牌,我们需要手动招聘:
@Configuration // ← 人力资源部
public class CompanyConfig {
@Bean // ← 手动签发聘书
public SpecialExpert specialExpert() {
return new SpecialExpert(); // 来自第三方库的专家
}
@Bean
public ProjectTeam projectTeam(Developer developer, SpecialExpert expert) {
// 管家会自动提供需要的依赖
return new ProjectTeam(developer, expert);
}
}
1.3 自动配置:管家的智能决策
Spring Boot最强大的特性就是自动配置。这就像管家根据公司环境自动做出最佳决策:
1.3.1 条件装配:智能的情境判断
@Configuration
public class SmartConfiguration {
// 只有当公司有数据库时,才招聘DBA
@Bean
@ConditionalOnClass(DataSource.class)
public DatabaseAdmin databaseAdmin() {
return new DatabaseAdmin();
}
// 只有当需要处理Web请求时,才配备Web团队
@Bean
@ConditionalOnWebApplication
public WebTeam webTeam() {
return new WebTeam();
}
// 只有当配置了邮件服务器时,才设立邮件部门
@Bean
@ConditionalOnProperty(name = "mail.host")
public EmailService emailService() {
return new EmailService();
}
}
1.3.2 源码揭秘:自动配置的工作原理
Spring Boot的自动配置是通过spring-boot-autoconfigure
包中的META-INF/spring.factories
文件实现的:
# spring.factories文件内容
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaAutoConfiguration
每个自动配置类都使用条件注解来决定是否生效:
@Configuration
@ConditionalOnClass(DataSource.class) // 有数据库驱动才生效
@ConditionalOnProperty(prefix = "spring.datasource", name = "url") // 配置了URL才生效
@EnableConfigurationProperties(DataSourceProperties.class) // 绑定配置属性
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 如果没有自定义DataSource才创建
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
1.4 实战示例:构建一个简单的公司系统
让我们用代码来演示Spring Boot如何基于注解管理IoC容器:
// 1. 启动类(公司总部)
@SpringBootApplication
public class CompanyApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(CompanyApplication.class, args);
// 从容器中获取bean
Project project = context.getBean(Project.class);
project.start();
}
}
// 2. 服务层(管理部门)
@Service
public class ProjectService {
private final Developer developer;
private final Designer designer;
// 构造器注入
public ProjectService(Developer developer, Designer designer) {
this.developer = developer;
this.designer = designer;
}
public void startProject() {
developer.code();
designer.design();
}
}
// 3. 组件类(员工)
@Component
public class Developer {
public void code() {
System.out.println("程序员编写代码...");
}
}
@Component
public class Designer {
public void design() {
System.out.println("设计师设计界面...");
}
}
// 4. 配置类(人力资源部)
@Configuration
public class CompanyConfig {
@Bean
public Project project(ProjectService projectService) {
return new Project(projectService);
}
}
// 5. 项目类
public class Project {
private final ProjectService projectService;
public Project(ProjectService projectService) {
this.projectService = projectService;
}
public void start() {
System.out.println("项目启动!");
projectService.startProject();
}
}
1.5 总结:注解驱动的IoC优势
通过注解驱动的方式,Spring Boot实现了:
- 简洁性:几个注解替代了大量XML配置
- 类型安全:编译期就能发现错误,而不是运行时
- 强一致性:注解与代码在一起,不会出现配置与代码不同步
- 智能自动配置:根据环境自动做出最佳决策
就像一位聪明的管家,Spring Boot通过注解了解你的需求,自动协调所有资源,让你可以专注于业务逻辑而不是基础设施的搭建。
记住这个比喻:
@Component
、@Service
、@Repository
、@Controller
→ 员工工牌@Autowired
→ 给员工配备助手和设备@Bean
→ 手动招聘特殊人才@Conditional
→ 管家的情境智能决策@SpringBootApplication
→ 总管家的聘书
有了这位智能管家,你的开发效率将大幅提升,真正实现"约定优于配置"的开发理念。