云计算百科
云计算领域专业知识百科平台

Spring依赖注入与自动装配解析

Spring依赖注入与自动装配解析

写在前面

如果你想深入学习SpringBoot的自动配置原理,那么本文是你必须掌握的基础知识。很多人在使用SpringBoot时,只知道用@Autowired注入依赖,却不知道背后的原理。

本文将从最基础的概念讲起,带你彻底理解Spring的依赖注入机制。无论你是刚接触Spring的新手,还是想复习巩固的老手,都能从本文获益。

适合人群: Spring初学者、准备深入学习SpringBoot的开发者、需要复习基础的工程师

一、核心概念:什么是Bean、依赖和注入

在学习依赖注入之前,我们必须先理解三个基本概念。

1.1 什么是Bean?

Bean就是由Spring容器管理的对象。

在传统Java开发中,我们这样创建对象:

UserService userService = new UserService();

而在Spring中,我们不需要自己new对象,而是让Spring容器帮我们创建和管理:

@Service // 告诉Spring:这是一个Bean,请帮我管理。@Service是@Component的衍生注解
public class UserService {
// …
}

形象的比喻:

  • 传统方式:你需要什么对象,自己new一个(自己做饭)
  • Spring方式:你告诉Spring需要什么,Spring给你创建好(外卖送餐)

Bean的特点:

  • 由Spring容器创建
  • 由Spring容器管理生命周期
  • 默认是单例的(整个应用只有一个实例)
  • 可以被其他Bean引用

1.2 什么是依赖?

依赖就是一个对象需要使用另一个对象来完成工作。

举个例子:

public class UserService {
private UserDao userDao; // UserService依赖UserDao

public User getUser(Long id) {
return userDao.findById(id); // 需要用到UserDao
}
}

在这个例子中:

  • UserService 需要 UserDao 才能完成查询用户的功能
  • 我们说:UserService 依赖 UserDao

生活中的例子:

  • 你要开车上班,你依赖汽车
  • 你要做饭,你依赖厨具
  • 你要写代码,你依赖电脑

1.3 什么是注入依赖?

注入依赖就是把一个对象需要的其他对象"送"给它。

传统方式(自己创建依赖):

public class UserService {
private UserDao userDao;

public UserService() {
this.userDao = new UserDaoImpl(); // 自己创建依赖
}
}

依赖注入方式(Spring帮你注入):

@Service
public class UserService {

@Autowired // 告诉Spring:请把UserDao注入给我
private UserDao userDao;
}

形象的比喻:

  • 传统方式:你要喝咖啡,自己买豆子、磨豆、煮咖啡(自己创建依赖)
  • 依赖注入:你要喝咖啡,告诉咖啡店,咖啡店做好送给你(Spring注入依赖)

依赖注入的好处:

  • 解耦:UserService不需要知道UserDao的具体实现
  • 易测试:可以轻松替换为Mock对象进行测试
  • 易维护:要换实现,不需要修改UserService代码
  • 统一管理:所有对象由Spring容器统一创建和管理
  • 二、控制反转(IoC):理解Spring的核心思想

    2.1 什么是控制反转?

    控制反转(Inversion of Control,IoC)是一种设计思想:把对象创建和管理的控制权交给框架。

    简单来说:就相当于框架帮你创建对象,只创建一次,那个类调用就把对象注入给谁

    好处:

  • 彻底解放双手:不用再手动new对象、手动传依赖
  • 统一管理对象:单例复用 + 生命周期全托管
    • 单例复用:框架创建的 Bean 默认是单例(只创建 1 次),所有需要这个对象的类,注入的都是同一个实例,避免重复创建对象浪费内存(比如一个UserDao对象,所有Service都用同一个,不用每次都new);
    • 生命周期托管:对象的 “创建→初始化→使用→销毁” 全由框架控制,你可以通过注解(如@PostConstruct初始化、@PreDestroy销毁)自定义流程,不用手动管理对象的生灭。
  • 降低代码耦合:类之间解耦,项目易维护、易扩展
  • 传统方式: 你控制一切

    public class UserService {
    private UserDao userDao;

    public UserService() {
    // 你决定创建什么对象
    this.userDao = new UserDaoImpl();
    }
    }

    IoC方式: Spring控制一切

    @Service
    public class UserService {
    @Autowired
    private UserDao userDao; // Spring决定注入什么对象
    }

    "反转"体现在哪里?

    维度传统方式IoC方式
    谁创建对象 你自己new Spring容器创建
    谁管理对象 你自己管理 Spring容器管理
    谁决定依赖 你在代码中写死 Spring根据配置决定

    核心思想: 不要打电话给我们,我们会打电话给你(Don’t call us, we’ll call you)

    2.2 IoC容器的作用

    Spring的IoC容器(ApplicationContext)就像一个对象工厂,负责:

  • 创建对象:根据配置创建Bean
  • 管理生命周期:从创建到销毁
  • 注入依赖:自动装配Bean之间的依赖关系
  • 提供服务:提供Bean的查找、获取等功能
  • // Spring容器启动时
    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

    // 从容器获取Bean
    UserService userService = context.getBean(UserService.class);

    // 这个userService已经注入好了所有依赖,可以直接使用
    User user = userService.getUser(1L);

    三、依赖注入的三种方式

    Spring支持三种依赖注入方式,每种都有各自的适用场景。

    方式1:字段注入(最常见但不推荐)

    @Service
    public class UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private EmailService emailService;
    }

    优点: 代码简洁,写起来方便

    缺点:

    • 无法注入final字段(不能保证不可变性)
    • 不利于单元测试(必须启动Spring容器或使用反射)
    • 违反了面向对象的封装原则
    • 依赖关系不明确

    方式2:构造器注入(强烈推荐)

    @Service
    //@RequiredArgsConstructor
    //Lombok注解,写了这个就不用写构造器了,但是要加入Lombok依赖。(依赖在博主之前的关于Lombok的文章中有提到过)
    public class UserService {

    private final UserDao userDao;
    private final EmailService emailService;

    // Spring 4.3+ 单构造器可省略@Autowired
    public UserService(UserDao userDao, EmailService emailService) {
    this.userDao = userDao;
    this.emailService = emailService;
    }
    }

    优点:

    • 可以使用final,保证不可变性和线程安全
    • 便于单元测试(直接new对象传参,无需Spring容器)
    • 依赖关系一目了然
    • 如果依赖过多,构造器参数会很长,提醒你类职责可能过重

    这是Spring官方推荐的方式!

    方式3:Setter方法注入

    @Service
    public class UserService {

    private UserDao userDao;

    @Autowired
    public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
    }
    }

    优点: 可以在对象创建后重新注入依赖(适合可选依赖)

    缺点: 依赖可能为null,不够安全

    三种方式对比:

    特性字段注入构造器注入Setter注入
    代码简洁度 最简洁 中等 较繁琐
    是否支持final
    测试友好度 中等
    依赖明确度 不明确 非常明确 较明确
    官方推荐度 不推荐 强烈推荐 适合可选依赖

    四、@Autowired与自动装配详解

    4.1 什么是自动装配?

    自动装配(Auto-Wiring)是Spring自动为Bean注入依赖的机制。

    简单来说:你只需要告诉Spring"我需要这个依赖"(通过@Autowired注解),Spring会自动帮你找到合适的Bean并注入进来。

    传统方式(手动装配):

    <bean id="userDao" class="com.example.dao.UserDaoImpl"/>
    <bean id="userService" class="com.example.service.UserService">
    <property name="userDao" ref="userDao"/> <!– 手动指定依赖 –>
    </bean>

    自动装配方式:

    @Service
    public class UserService {
    @Autowired // 自动装配,Spring自动找到UserDao并注入
    private UserDao userDao;
    }

    4.2 自动装配的演进历史

    阶段1:XML时代(Spring 1.x – 2.x)

    <!– 按类型自动装配 –>
    <bean id="userService" class="com.example.service.UserService"
    autowire="byType"/>

    <!– 按名称自动装配 –>
    <bean id="userService" class="com.example.service.UserService"
    autowire="byName"/>

    阶段2:注解时代(Spring 2.5+)

    @Service
    public class UserService {
    @Autowired // 注解方式,更简洁
    private UserDao userDao;
    }

    阶段3:纯Java配置时代(Spring 3.0+)

    Spring 3.0 引入了 @Configuration 和 @Bean:

    @Configuration
    public class AppConfig {

    @Bean
    public UserDao userDao() {
    return new UserDaoImpl();
    }

    @Bean
    public UserService userService() {
    return new UserService(); // 自动装配
    }
    }

    阶段4:SpringBoot时代(Spring 4.0+)

    @SpringBootApplication // 自动扫描,自动装配
    public class Application {
    public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
    }
    }

    4.3 自动装配的工作原理

    核心处理器: AutowiredAnnotationBeanPostProcessor

    完整流程:

    1. Spring容器启动,扫描所有Bean定义

    2. 创建Bean实例(调用构造函数)

    3. AutowiredAnnotationBeanPostProcessor介入

    4. 扫描Bean中的@Autowired注解

    5. 解析依赖类型

    6. 在容器中查找匹配的Bean
    ├─ 按类型查找(byType)- 默认策略
    ├─ 如果有多个,按@Primary筛选
    ├─ 如果还有多个,按@Qualifier筛选
    └─ 如果还有多个,按字段名称匹配

    7. 通过反射注入依赖

    8. Bean初始化完成

    4.4 自动装配的匹配策略

    策略1:按类型匹配(byType)- 默认

    @Service
    public class UserService {
    @Autowired
    private UserDao userDao; // 查找UserDao类型的Bean
    }

    • 找到1个 → 直接注入
    • 找到0个 → 抛出异常(除非required=false)
    • 找到多个 → 继续下一步匹配

    策略2:按@Primary匹配 – 优先级

    @Repository
    @Primary // 标记为首选
    public class UserDaoMysqlImpl implements UserDao { }

    @Repository
    public class UserDaoMongoImpl implements UserDao { }

    @Service
    public class UserService {
    @Autowired
    private UserDao userDao; // 自动选择@Primary标记的Bean
    }

    策略3:按@Qualifier匹配 – 明确指定

    @Service
    public class UserService {
    @Autowired
    @Qualifier("userDaoMongoImpl") // 明确指定使用哪个Bean
    private UserDao userDao;
    }

    策略4:按字段名称匹配 – 辅助

    @Service
    public class UserService {
    @Autowired
    private UserDao userDaoMysqlImpl; // 字段名与Bean名称一致
    }

    策略5:注入集合 – 获取所有实现

    @Service
    public class UserService {
    // 注入所有UserDao类型的Bean
    @Autowired
    private List<UserDao> userDaoList;

    // 注入所有UserDao类型的Bean到Map,key为Bean名称
    @Autowired
    private Map<String, UserDao> userDaoMap;
    }

    匹配优先级:

    @Qualifier(最高优先级)

    @Primary

    字段名称匹配

    类型匹配(默认)

    4.5 处理多个候选Bean

    当容器中有多个相同类型的Bean时:

    // 有两个UserDao的实现
    @Repository
    public class UserDaoMysqlImpl implements UserDao { }

    @Repository
    public class UserDaoMongoImpl implements UserDao { }

    // 注入时会报错
    @Service
    public class UserService {
    @Autowired
    private UserDao userDao; // 错误:找到2个候选Bean
    }

    解决方案总结:

    方案代码示例适用场景
    @Qualifier @Qualifier("userDaoMysqlImpl") 明确知道要用哪个Bean
    @Primary 在Bean上加@Primary 有一个默认首选实现
    字段名匹配 private UserDao userDaoMysqlImpl 简单场景
    注入List/Map List<UserDao> userDaoList 需要使用所有实现

    4.6 可选依赖的处理

    方式1:使用required=false

    @Service
    public class UserService {
    @Autowired(required = false) // 找不到Bean不报错,注入null
    private CacheService cacheService;

    public User getUser(Long id) {
    if (cacheService != null) {
    User cached = cacheService.get(id);
    if (cached != null) return cached;
    }
    return userDao.findById(id);
    }
    }

    方式2:使用Optional(更优雅)

    @Service
    public class UserService {
    @Autowired
    private Optional<CacheService> cacheService;

    public User getUser(Long id) {
    return cacheService
    .map(cache -> cache.get(id))
    .orElseGet(() -> userDao.findById(id));
    }
    }

    4.7 自动装配的注意事项

    注意1:理解装配时机

    自动装配发生在Bean的属性注入阶段,在构造函数之后:

    @Service
    public class UserService {
    @Autowired
    private UserDao userDao;

    public UserService() {
    // 错误:此时userDao还未注入,为null
    // userDao.findAll();
    }

    @PostConstruct
    public void init() {
    // 正确:此时userDao已经注入
    userDao.findAll();
    }
    }

    注意2:避免循环依赖

    // 不推荐:循环依赖
    @Service
    public class UserService {
    @Autowired
    private OrderService orderService;
    }

    @Service
    public class OrderService {
    @Autowired
    private UserService userService;
    }

    // 推荐:重新设计,单向依赖
    @Service
    public class OrderService {
    @Autowired
    private UserService userService; // 单向依赖
    }

    4.8 自动装配与SpringBoot自动配置的区别

    很多人容易混淆这两个概念:

    自动装配(Auto-Wiring):

    • Spring的核心功能
    • 负责注入依赖
    • 通过@Autowired实现
    • Bean已存在,只是注入

    自动配置(Auto-Configuration):

    • SpringBoot的特性
    • 负责创建Bean
    • 通过@EnableAutoConfiguration实现
    • 根据条件自动创建Bean

    关系:

    SpringBoot自动配置 → 创建Bean

    Spring自动装配 → 注入Bean

    举例:

    // SpringBoot自动配置:自动创建DataSource Bean
    @Configuration
    @ConditionalOnClass(DataSource.class)
    public class DataSourceAutoConfiguration {
    @Bean
    public DataSource dataSource() {
    return DataSourceBuilder.create().build();
    }
    }

    // 自动装配:自动注入DataSource依赖
    @Service
    public class UserService {
    @Autowired // 自动装配
    private DataSource dataSource; // 这个Bean是自动配置创建的
    }

    五、其他注入注解对比

    5.1 @Resource(JSR-250规范)

    @Service
    public class UserService {

    @Resource // 默认按名称装配
    private UserDao userDao;

    @Resource(name = "userDaoMysqlImpl") // 指定Bean名称
    private UserDao userDao2;
    }

    @Autowired vs @Resource:

    特性@Autowired@Resource
    来源 Spring框架 Java EE规范
    默认装配方式 按类型(byType) 按名称(byName)
    指定Bean 配合@Qualifier 使用name属性
    支持required 支持 不支持
    支持构造器注入 支持 不支持

    建议: 优先使用@Autowired,功能更强大,是Spring原生注解。

    5.2 @Inject(JSR-330)

    来自Java依赖注入规范:

    @Service
    public class UserService {

    @Inject // 功能类似@Autowired
    private UserDao userDao;
    }

    需要额外引入依赖:

    <dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
    </dependency>

    @Inject vs @Autowired:

    特性@Autowired@Inject
    来源 Spring JSR-330
    是否支持required 支持 不支持
    配合注解 @Qualifier @Named

    建议: 除非需要跨框架兼容,否则使用 @Autowired 即可。

    5.3 @Value(注入配置值)

    用于注入配置文件中的值,这是学习SpringBoot配置的基础:

    @Service
    public class UserService {

    @Value("${app.name}") // 从配置文件读取
    private String appName;

    @Value("${app.max-users:100}") // 指定默认值100
    private int maxUsers;

    @Value("#{systemProperties['user.home']}") // SpEL表达式
    private String userHome;
    }

    配置文件(application.properties):

    app.name=我的应用
    app.max-users=500

    六、常见问题与解决方案

    问题1:循环依赖

    什么是循环依赖?

    两个或多个Bean相互依赖,形成闭环:

    @Service
    public class UserService {
    @Autowired
    private OrderService orderService; // UserService依赖OrderService
    }

    @Service
    public class OrderService {
    @Autowired
    private UserService userService; // OrderService依赖UserService
    }

    Spring如何解决?

    Spring通过三级缓存机制解决单例Bean的字段注入循环依赖:

  • 一级缓存:存放完整的Bean实例
  • 二级缓存:存放早期的Bean引用(已实例化但未完成依赖注入)
  • 三级缓存:存放Bean工厂(用于创建代理对象)
  • 无法解决的情况:构造器循环依赖

    @Service
    public class UserService {
    private final OrderService orderService;

    public UserService(OrderService orderService) {
    this.orderService = orderService;
    }
    }

    @Service
    public class OrderService {
    private final UserService userService;

    public OrderService(UserService userService) {
    this.userService = userService; // 报错!无法解决
    }
    }

    解决方法:

  • 重新设计,消除循环依赖(最佳方案)
  • 使用@Lazy延迟加载
  • @Service
    public class UserService {
    private final OrderService orderService;

    public UserService(@Lazy OrderService orderService) {
    this.orderService = orderService; // 注入代理对象,延迟初始化
    }
    }

  • 改用字段注入(不推荐,只是权宜之计)
  • 问题2:注入的Bean为null

    常见原因:

    原因1:类没有被Spring管理

    // 错误:忘记加@Service注解
    public class UserService {
    @Autowired
    private UserDao userDao; // 注入失败,为null
    }

    // 正确:添加@Service注解
    @Service
    public class UserService {
    @Autowired
    private UserDao userDao; // 正常注入
    }

    原因2:包扫描路径不对

    @SpringBootApplication
    @ComponentScan("com.example.service") // 只扫描service包
    public class Application {
    // UserDao在com.example.dao包下,扫描不到
    }

    // 正确:扫描父包
    @SpringBootApplication
    @ComponentScan("com.example") // 扫描整个com.example包
    public class Application { }

    原因3:直接new对象,不从Spring容器获取

    // 错误:直接new的对象,Spring无法注入依赖
    UserService service = new UserService();
    service.getUser(1L); // userDao为null,报NPE

    // 正确:从Spring容器获取
    @RestController
    public class UserController {

    @Autowired
    private UserService userService; // 从容器获取,依赖已注入

    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Long id) {
    return userService.getUser(id); // 正常使用
    }
    }

    原因4:在静态字段上使用@Autowired

    // 错误:无法注入静态字段
    @Service
    public class UserService {
    @Autowired
    private static UserDao userDao; // 无法注入
    }

    // 正确:使用非静态字段
    @Service
    public class UserService {
    @Autowired
    private UserDao userDao; // 正常注入
    }

    问题3:注入时机问题

    错误示例:在构造函数中使用依赖

    @Service
    public class UserService {

    @Autowired
    private UserDao userDao;

    private List<User> cache;

    // 错误:构造函数执行时,userDao还未注入
    public UserService() {
    this.cache = userDao.findAll(); // NPE!
    }
    }

    正确做法:使用@PostConstruct

    @Service
    public class UserService {

    @Autowired
    private UserDao userDao;

    private List<User> cache;

    @PostConstruct // 在依赖注入完成后执行
    public void init() {
    this.cache = userDao.findAll(); // 正确
    }
    }

    Bean的生命周期:

    1. 实例化(执行构造函数)

    2. 依赖注入(@Autowired生效)

    3. 初始化前(@PostConstruct执行)

    4. 初始化(InitializingBean.afterPropertiesSet())

    5. Bean可用

    6. 销毁前(@PreDestroy执行)

    7. 销毁(DisposableBean.destroy())

    七、最佳实践

    1. 优先使用构造器注入

    // 推荐
    @Service
    public class UserService {
    private final UserDao userDao; // final保证线程安全

    public UserService(UserDao userDao) {
    this.userDao = userDao;
    }
    }

    //或者可以这样写,一个意思

    @Service
    @@RequiredArgsConstructor
    public class UserService {
    private final UserDao userDao;
    }

    2. 使用final保证不可变性

    @Service
    public class UserService {
    private final UserDao userDao; // final保证线程安全

    public UserService(UserDao userDao) {
    this.userDao = userDao;
    }
    }

    3. 多个相同类型Bean时明确指定

    @Service
    public class UserService {
    private final UserDao userDao;

    public UserService(@Qualifier("userDaoMysqlImpl") UserDao userDao) {
    this.userDao = userDao;
    }
    }

    4. 可选依赖使用Optional

    @Service
    public class UserService {
    @Autowired
    private Optional<CacheService> cacheService;
    }

    5. 避免循环依赖

    重新设计类的职责,消除循环依赖。如果实在无法避免,使用@Lazy。

    八、面试高频问题

    问题1:@Autowired和@Resource的区别?

    答案:

    维度@Autowired@Resource
    来源 Spring框架 Java EE规范(JSR-250)
    装配方式 默认byType,可配合@Qualifier按名称 默认byName,可通过name属性指定
    作用范围 字段、构造器、方法、参数 字段、方法
    required属性 支持 不支持
    推荐使用 Spring项目推荐 需要跨框架兼容时使用

    问题2:什么是循环依赖?Spring如何解决?

    答案:

    循环依赖是指两个或多个Bean相互依赖,形成闭环。

    Spring通过三级缓存解决单例Bean的循环依赖:

  • 一级缓存:完整的Bean实例
  • 二级缓存:早期的Bean引用(未完成依赖注入)
  • 三级缓存:Bean工厂(用于创建代理对象)
  • 注意: 构造器循环依赖无法解决,需要使用@Lazy或重新设计。

    问题3:为什么推荐使用构造器注入?

    答案:

  • 依赖明确:所有依赖在构造器中声明,一目了然
  • 不可变性:可以使用final修饰,保证线程安全
  • 便于测试:可以直接new对象传参,无需Spring容器
  • 避免NPE:如果依赖为null,在创建时就会失败
  • 强制完整性:必须提供所有依赖才能创建对象
  • 问题4:@Autowired的装配流程是什么?

    答案:

  • Bean实例化(调用构造函数)
  • AutowiredAnnotationBeanPostProcessor 扫描@Autowired注解
  • 解析依赖类型
  • 在容器中查找匹配的Bean:
    • 先按类型查找
    • 如果有多个,按@Primary筛选
    • 如果还有多个,按@Qualifier筛选
    • 如果还有多个,按字段名称匹配
  • 通过反射注入依赖
  • 调用@PostConstruct方法
  • Bean初始化完成
  • 问题5:如何解决多个相同类型Bean的注入问题?

    答案:

  • 使用 @Qualifier 指定Bean名称
  • 使用 @Primary 标记主要Bean
  • 使用字段名称匹配Bean名称
  • 注入 List<T> 或 Map<String, T> 获取所有Bean
  • 使用 @Resource(name="beanName") 按名称注入
  • 问题6:依赖注入和工厂模式有什么区别?

    答案:

    工厂模式:

    • 对象自己通过工厂获取依赖
    • 对象知道工厂的存在
    • 耦合度较高

    依赖注入:

    • 容器主动将依赖注入到对象
    • 对象不知道容器的存在
    • 完全解耦

    依赖注入是控制反转的一种实现方式,比工厂模式更彻底地解耦。

    九、与SpringBoot的关系

    理解了Spring的依赖注入,你就能更好地理解SpringBoot的自动配置原理。

    SpringBoot如何简化依赖注入?

  • 自动包扫描
  • @SpringBootApplication // 包含@ComponentScan,自动扫描当前包及子包
    //目标类标注 @Component 或其衍生注解,且类处于启动类所在包/子包下,SpringBoot 就会自动扫描并将其注册为 Bean 实例。
    public class Application {
    public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
    }
    }

  • 自动配置Bean
  • SpringBoot会自动配置常用的Bean(如DataSource、JdbcTemplate等),你只需注入使用:

    @Service
    public class UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate; // SpringBoot自动配置,直接注入
    }

  • Starter依赖
  • 引入starter依赖,相关Bean自动配置:

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    @Service
    public class UserService {
    @Autowired
    private EntityManager entityManager; // 自动配置,直接注入
    }

    本文是学习SpringBoot的基础:

    • SpringBoot的自动配置本质上就是自动创建Bean并注入依赖
    • 理解了依赖注入,才能理解@ConditionalOnBean等条件注解
    • 理解了依赖注入,才能理解Starter的工作原理

    下一步学习: 阅读《SpringBoot自动配置原理深度解析》,理解SpringBoot如何自动创建和配置Bean。

    十、推荐资源

    官方文档

    • Spring Framework Reference:https://docs.spring.io/spring-framework/docs/current/reference/html/
    • Spring IoC Container:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans

    源码阅读

    • Spring Framework:https://github.com/spring-projects/spring-framework
    • 重点类:
      • AutowiredAnnotationBeanPostProcessor
      • DefaultListableBeanFactory
      • AbstractAutowireCapableBeanFactory

    十一、总结

    核心要点:

  • Bean是由Spring容器管理的对象
  • 依赖是一个对象需要使用另一个对象
  • 依赖注入是Spring把依赖对象注入给需要的对象
  • 控制反转是把对象创建和管理的控制权交给Spring
  • @Autowired默认按类型装配,可配合@Qualifier按名称
  • 构造器注入是最佳实践,优于字段注入
  • 循环依赖通过三级缓存解决,但构造器循环依赖无法解决
  • 学习路线:

    Spring依赖注入(本文)

    SpringBoot自动配置原理

    自定义Starter开发

    Spring AOP原理

    Spring事务管理

    给读者的建议:

  • 动手实践:写代码,打断点调试
  • 阅读源码:看看AutowiredAnnotationBeanPostProcessor的实现
  • 理解原理:知其然更要知其所以然
  • 实际应用:在项目中使用最佳实践

  • 如果这篇文章对你有帮助,请点赞、收藏、关注!有问题欢迎在评论区讨论。

    作者:[识君啊]

    不要做API的搬运工,要做原理的探索者!

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Spring依赖注入与自动装配解析
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!