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

 更新时间:2026年02月09日 11:26:31   作者:识君啊  
本文讲解Spring依赖注入核心知识:阐释 Bean、IoC 等概念,介绍三种注入方式(推荐构造器注入),解析 @Autowired 自动装配原理、注解差异及循环依赖等问题的解决办法,感兴趣的朋友跟随小编一起看看吧

写在前面

如果你想深入学习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注入依赖)

依赖注入的好处:

  1. 解耦:UserService不需要知道UserDao的具体实现
  2. 易测试:可以轻松替换为Mock对象进行测试
  3. 易维护:要换实现,不需要修改UserService代码
  4. 统一管理:所有对象由Spring容器统一创建和管理

二、控制反转(IoC):理解Spring的核心思想

2.1 什么是控制反转?

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

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

好处

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

传统方式: 你控制一切

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

IoC方式: Spring控制一切

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

"反转"体现在哪里?

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

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

2.2 IoC容器的作用

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

  1. 创建对象:根据配置创建Bean
  2. 管理生命周期:从创建到销毁
  3. 注入依赖:自动装配Bean之间的依赖关系
  4. 提供服务:提供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/MapList<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
来源SpringJSR-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的字段注入循环依赖:

  1. 一级缓存:存放完整的Bean实例
  2. 二级缓存:存放早期的Bean引用(已实例化但未完成依赖注入)
  3. 三级缓存:存放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;  // 报错!无法解决
    }
}

解决方法:

  1. 重新设计,消除循环依赖(最佳方案)
  2. 使用@Lazy延迟加载
@Service
public class UserService {
    private final OrderService orderService;
    public UserService(@Lazy OrderService orderService) {
        this.orderService = orderService;  // 注入代理对象,延迟初始化
    }
}
  1. 改用字段注入(不推荐,只是权宜之计)

问题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的循环依赖:

  1. 一级缓存:完整的Bean实例
  2. 二级缓存:早期的Bean引用(未完成依赖注入)
  3. 三级缓存:Bean工厂(用于创建代理对象)

注意: 构造器循环依赖无法解决,需要使用@Lazy或重新设计。

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

答案:

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

问题4:@Autowired的装配流程是什么?

答案:

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

问题5:如何解决多个相同类型Bean的注入问题?

答案:

  1. 使用 @Qualifier 指定Bean名称
  2. 使用 @Primary 标记主要Bean
  3. 使用字段名称匹配Bean名称
  4. 注入 List<T>Map<String, T> 获取所有Bean
  5. 使用 @Resource(name="beanName") 按名称注入

问题6:依赖注入和工厂模式有什么区别?

答案:

工厂模式:

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

依赖注入:

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

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

九、与SpringBoot的关系

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

SpringBoot如何简化依赖注入?

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

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

@Service
public class UserService {
    @Autowired
    private JdbcTemplate jdbcTemplate;  // SpringBoot自动配置,直接注入
}
  1. 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

十一、总结

核心要点:

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

学习路线:

Spring依赖注入(本文)
    ↓
SpringBoot自动配置原理
    ↓
自定义Starter开发
    ↓
Spring AOP原理
    ↓
Spring事务管理

给读者的建议:

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

到此这篇关于Spring依赖注入与自动装配原理解析的文章就介绍到这了,更多相关spring依赖注入与自动装配内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决springboot mapper注入报红问题

    解决springboot mapper注入报红问题

    这篇文章主要介绍了解决springboot mapper注入报红问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Javaweb使用getPart接收表单文件过程解析

    Javaweb使用getPart接收表单文件过程解析

    这篇文章主要介绍了Javaweb使用getPart接收表单文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Spring BeanFactory和FactoryBean有哪些区别

    Spring BeanFactory和FactoryBean有哪些区别

    这篇文章主要介绍了Spring BeanFactory 与 FactoryBean 的区别详情,BeanFactory 和 FactoryBean 的区别却是一个很重要的知识点,在本文中将结合源码进行分析讲解,需要的小伙伴可以参考一下
    2023-02-02
  • Java反射简易教程

    Java反射简易教程

    这篇文章主要介绍了Java反射简易教程,小编觉得挺不错的,这里分享给大家,需要的朋友可以参考。
    2017-11-11
  • Javaweb动态开发最重要的Servlet详解

    Javaweb动态开发最重要的Servlet详解

    动态web的核心是Servlet,由tomcat解析并执行,本质是Java中的一个类(面向对象)这个类的功能十分强大几乎可以完成全部功能,在Java规范中只有Servlet实现类实例化的对象才能被浏览器访问,所以掌握Servlet具有重要意义
    2022-08-08
  • Java IO流之原理分类与节点流文件操作详解

    Java IO流之原理分类与节点流文件操作详解

    流(Stream)是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道,数据源发送的数据经过这个通道到达目的地,按流向区分为输入流和输出流
    2021-10-10
  • 在 Java 中将Object 转换为 Int的四种方法

    在 Java 中将Object 转换为 Int的四种方法

    这篇文章主要介绍了在Java中如何将 Object 转换为Int,本文研究了在 Java中将Object转换为int的四种不同方法,结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • SpringBoot整合XxlJob分布式任务调度平台

    SpringBoot整合XxlJob分布式任务调度平台

    xxl-job是一个开源的分布式定时任务框架,它可以与其他微服务组件一起构成微服务集群。它的调度中心(xxl-job)和执行器(自己的springboot项目中有@XxlJob("定时任务名称")的方法)是相互分离,分开部署的,两者通过HTTP协议进行通信
    2023-02-02
  • springMVC返回Http响应的实现

    springMVC返回Http响应的实现

    本文主要介绍了在Spring Boot中使用@Controller、@ResponseBody和@RestController注解进行HTTP响应返回的方法,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • QueryWrapper中or的使用技巧分享

    QueryWrapper中or的使用技巧分享

    在日常的开发工作中,处理数据库查询是一个非常常见的任务,尤其是当我们需要在复杂条件下筛选数据时,如何编写高效、简洁且可维护的查询逻辑显得尤为重要,本文给大家介绍了QueryWrapper中or的使用技巧,需要的朋友可以参考下
    2024-10-10

最新评论