【Springframework系列 依赖注入】

依赖注入概念

Spring官方解释

依赖注入(DI)是一个过程,对象仅通过构造参数、工厂方法的参数或在对象实例被构造或从工厂方法返回后在其上设置的属性来定义它们的依赖(即与它们一起工作的其它对象)。然后,容器在创建 bean 时注入这些依赖。这个过程从根本上说是Bean本身通过使用类的直接构造或服务定位模式来控制其依赖的实例化或位置的逆过程(因此被称为控制反转)。

通俗易懂的话

当需要在一个对象中使用另一个不同对象时,需要将另一个对象进行实例化操作。

如:在方法中需要使用另一个对象

// 自己买菜、切菜、炒菜
class Chef {
    public void cook() {
        Vegetable veggie = new Vegetable();  // 强依赖
        Pan pan = new Pan();                // 强依赖
        pan.fry(veggie);
    }
}

使用依赖注入方式

class Chef {
    private Ingredient ingredient; // 食材由外卖员送来
    private CookTool tool;        // 厨具由外卖员送来

    // 外卖员(Spring)自动送食材和厨具进来
    public Chef(Ingredient ingredient, CookTool tool) {
        this.ingredient = ingredient;
        this.tool = tool;
    }

    public void cook() {
        tool.fry(ingredient);  // 直接用现成的
    }
}

将目标对象注入到Spring容器

Springframework 提供了一系列注解支持将目标对象注入到Spring容器中。如:

  • @Controller
  • @Service
  • @Repository
  • @Component
    等等。

为目标对象打上这些注解后,Spring自动会扫描对象中是否有:

  • 构造函数
  • setter方法

如果目标对象没有提供显示构造,则会使用Java提供的默认隐式构造。

依赖注入方式

  • 通过构造器注入
public class Chef {
    // 必需依赖(final 字段,不可变)
    private final Ingredient ingredient;
    private final CookTool tool;

    // 构造器注入(Spring 会自动调用)
    public Chef(Ingredient ingredient, CookTool tool) {
        this.ingredient = ingredient;
        this.tool = tool;
    }

    public void cook() {
        tool.use(ingredient);
        System.out.println("菜做好了!");
    }
}
  • 通过setter注入
public class Chef {
    // 可选依赖(非 final 字段)
    private Ingredient ingredient;
    private CookTool tool;

    // Setter 注入(Spring 会自动调用)
    public void setIngredient(Ingredient ingredient) {
        this.ingredient = ingredient;
    }

    public void setTool(CookTool tool) {
        this.tool = tool;
    }

    public void cook() {
        if (ingredient == null || tool == null) {
            throw new IllegalStateException("缺少食材或厨具!");
        }
        tool.use(ingredient);
        System.out.println("菜做好了!");
    }
}

@Autowired与构造器注入

对比维度构造器注入@Autowired 字段注入
依赖不可变性✅ 可用 final 字段❌ 字段可变(可能被反射修改)
线程安全✅ 对象创建后依赖不可变❌ 依赖可能被并发修改
单元测试友好度✅ 直接 new MyService(mockRepo)❌ 需用反射或 Spring 容器
循环依赖检测✅ 启动时立即发现❌ 可能运行时才暴露问题
代码简洁性❌ 需显式写构造器(可用 Lombok 简化)✅ 字段上加一行注解即可
Spring 推荐度⭐⭐⭐⭐⭐(官方推荐)⭐⭐(历史遗留用法,不推荐新项目)
适用场景强依赖、核心服务快速原型开发(但生产环境应避免)

总结

用构造器依赖注入是最安全最稳健的,但是考虑到便捷性等因素,实际开发中可能会使用@Autowired、@Resource等更具便捷性的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值