深入理解Spring的依赖注入(DI):解锁松耦合设计的奥秘!

举报
bug菌 发表于 2025/05/30 17:30:04 2025/05/30
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

🚀 前言 🔍

  如果你曾经在开发过程中被“代码耦合”问题困扰过,那么你一定会对依赖注入(Dependency Injection, DI)这个概念感到兴奋。依赖注入是Spring框架中一个非常核心的概念,它通过将对象的创建交给Spring容器来管理,帮助我们实现松耦合的代码结构,从而提高代码的可维护性和灵活性。

  今天,我们将深入探讨依赖注入的概念,自动装配(autowire)方式,以及如何通过不同的注入方式(构造器、Setter和接口注入)来实现高效的依赖管理。

💡 什么是依赖注入(DI)?

  依赖注入(DI)是一种设计模式,用于实现类之间的解耦。在没有DI的情况下,一个类通常会直接创建其他类的实例,形成紧密耦合。随着项目的复杂性增加,这种耦合关系会使得代码难以维护和扩展。

  依赖注入的核心思想是,将对象的创建交给Spring容器来管理,而不是由类自己来创建,这样类之间的依赖关系就会变得更加灵活,代码的耦合度大大降低。

  简而言之,DI允许对象之间的依赖关系由外部容器注入,而不是由对象本身创建

  我们来看一个简单的例子:

public class Car {
    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.run();
    }
}

public class Engine {
    public void run() {
        System.out.println("Engine is running...");
    }
}

  在这个例子中,Car类直接依赖于Engine类。通过构造器注入,我们可以将Engine类的实例传递给Car类,而不是让Car类自己去创建Engine实例。

🔄 自动装配(autowire)方式:byName、byType、constructor

  Spring框架提供了几种自动装配的方式来帮助开发者更方便地实现依赖注入。自动装配方式的本质是让Spring容器根据配置自动为类的依赖项注入正确的实例。

1. byName(按名称自动装配)

  通过byName方式,Spring容器会根据属性的名称来匹配容器中已经定义的bean名称,从而注入依赖。如果Car类的engine属性的名称与容器中某个bean的名称匹配,那么Spring就会自动注入该bean。

<bean id="car" class="com.example.Car">
    <property name="engine" ref="engine"/>
</bean>

<bean id="engine" class="com.example.Engine"/>

  在这个例子中,Spring会根据Car类的engine属性名称来寻找容器中名为engine的bean,并自动注入。

2. byType(按类型自动装配)

  byType方式则是根据属性的类型来进行自动装配。在容器中,Spring会寻找与属性类型匹配的bean,并将其注入。

<bean id="car" class="com.example.Car">
    <property name="engine" ref="engine"/>
</bean>

<bean id="engine" class="com.example.Engine"/>

  在这个例子中,Car类的engine属性类型是Engine,Spring会自动查找类型为Engine的bean,并将其注入。

3. constructor(按构造器自动装配)

  通过构造器自动装配,Spring会根据构造器参数的类型来匹配容器中的bean。这种方式适用于需要依赖多个bean的情况,能够更加明确地表明依赖关系。

<bean id="car" class="com.example.Car">
    <constructor-arg ref="engine"/>
</bean>

<bean id="engine" class="com.example.Engine"/>

  在这个例子中,Car类通过构造器注入Engine实例,Spring根据构造器参数类型进行自动装配。

🛠️ @Autowired注解的使用:简化注入过程

  为了让依赖注入更加简便,Spring引入了@Autowired注解。通过@Autowired,你可以将依赖注入的过程声明得更加简洁,无需再在XML配置文件中进行繁琐的bean定义。

构造器注入

  使用@Autowired注解,可以直接在构造器上标注注解,Spring会自动注入依赖的bean:

@Component
public class Car {
    private final Engine engine;

    @Autowired
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.run();
    }
}

  在这个例子中,Car类的构造器带有@Autowired注解,Spring会自动为engine参数注入Engine类型的bean。

Setter注入

  你还可以选择使用Setter方法进行注入:

@Component
public class Car {
    private Engine engine;

    @Autowired
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.run();
    }
}

  Spring会调用setEngine方法来注入Engine对象,确保Car类能够正常运行。

字段注入

  如果你喜欢更简洁的写法,Spring还允许你直接在字段上使用@Autowired注解:

@Component
public class Car {
    @Autowired
    private Engine engine;

    public void start() {
        engine.run();
    }
}

  这种方式不需要显示的构造器或Setter方法,Spring会直接将Engine实例注入到Car类的engine字段。

🔄 Spring中的依赖注入模式:构造器注入、Setter注入、接口注入

  Spring框架提供了几种不同的依赖注入模式,分别适用于不同的需求和场景。接下来我们来详细了解一下这三种注入方式。

1. 构造器注入(Constructor Injection)

  构造器注入是一种最常见的依赖注入方式,通常用于必须提供依赖的类。它通过构造器参数来注入依赖,这使得依赖关系在创建对象时就被明确指出。构造器注入有助于在对象实例化时确保所有必需的依赖都被提供。

@Component
public class Car {
    private final Engine engine;

    @Autowired
    public Car(Engine engine) {
        this.engine = engine;
    }
}

2. Setter注入(Setter Injection)

  Setter注入是通过Setter方法注入依赖。这种方式通常用于依赖不是必需的场景,或者需要在对象创建后修改依赖的情况。Setter注入的灵活性较高,但它不能保证依赖在对象创建时就被提供。

@Component
public class Car {
    private Engine engine;

    @Autowired
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
}

3. 接口注入(Interface Injection)

  接口注入相对较少使用,通常通过实现某个接口来注入依赖。在Spring中,接口注入方式较少见,通常不推荐使用。

public interface EngineAware {
    void setEngine(Engine engine);
}

@Component
public class Car implements EngineAware {
    private Engine engine;

    @Override
    @Autowired
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
}

🎯 总结:依赖注入的核心价值

  通过依赖注入,Spring框架帮助我们实现了松耦合、模块化和高效的代码结构。无论是使用构造器注入、Setter注入,还是字段注入,我们都能够简化对象之间的依赖管理,提高系统的灵活性与可测试性。

  通过@Autowired注解,我们可以更加简洁地实现依赖注入,极大地提升了开发效率和代码的可读性。随着项目的规模逐渐增大,合理地使用依赖注入模式将为我们的应用程序带来更好的可维护性和扩展性。

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。