前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Framework IoC依赖注入-按Bean类型注入

Spring Framework IoC依赖注入-按Bean类型注入

作者头像
关忆北.
发布2023-11-22 11:02:01
1390
发布2023-11-22 11:02:01
举报
文章被收录于专栏:关忆北.关忆北.

theme: smartblue

Spring Framework 作为一个领先的企业级开发框架,以其强大的依赖注入(Dependency Injection,DI)机制而闻名。DI使得开发者可以更加灵活地管理对象之间的关系,而不必过多关注对象的创建和组装。在Spring Framework中,依赖注入可以分为两种类型:根据Bean名称注入、根据Bean类型注入,在本文中,我们将聚焦于 Spring 中的一种依赖注入方式——按类型注入,并通过一个简单的示例来说明其使用和优势。

什么是依赖注入?

don’t call us, we’ll call you

依赖注入是一种先进的设计思想,它通过外部注入依赖对象来实现组件之间的松耦合。在 Spring 框架中,依赖注入的核心实现便是通过控制反转(Inversion of Control,IoC)容器。IoC 容器负责实例化、配置和组装应用中的对象,并在需要时将它们智能地注入到其他对象中。相较于传统的面向对象思想,当业务代码变得复杂时,通过直接使用 new 进行对象构造对象间的关系,容易导致代码耦合度的上升。Spring 通过控制反转巧妙地解决了这一问题,运用了好莱坞原则的理念:不要给我们打电话,我们会给你打电话。这种思想使得代码更加灵活、可维护,并促使了更优雅的代码结构。

pexels-masood-aslami-19012241.jpg
pexels-masood-aslami-19012241.jpg

Spring 中的依赖注入

在 Spring 中,依赖注入有多种方式,包括构造函数注入、Setter 方法注入、接口注入等。示例中展示的是一种基于 XML 配置的 Setter 方法注入。

构造函数注入的案例:
代码语言:javascript
复制
public class UserService {

    private final EmailService emailService;

    // 构造函数注入
    public UserService(EmailService emailService) {
        this.emailService = emailService;
    }

    public void sendWelcomeEmail(String username) {
        String message = "Welcome, " + username + "!";
        emailService.sendEmail("welcome@example.com", message);
    }
}
Setter 方法注入的案例:
代码语言:javascript
复制
public class NotificationServiceClient {

    private NotificationService notificationService;

    // Setter 方法注入
    public void setNotificationService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public void sendNotification(String message) {
        notificationService.notifyUser(message);
    }
}
```java

### 接口注入的案例:

public class LoggingService {

代码语言:javascript
复制
private Logger logger;

// 接口注入
public void setLogger(Logger logger) {
    this.logger = logger;
}

public void logMessage(String message) {
    logger.log(message);
}

}

代码语言:javascript
复制
在本文中以知名IP:小马哥在《小马哥讲 Spring 核心编程思想》中使用的代码案例展开。

Github源码:

[GeekTime](https://gitee.com/geektime-geekbang/geekbang-lessons.git)

dependency-injection-context.xml

```xml
<!-- 通过导入复用 dependency-lookup-context.xml -->
<import resource="dependency-lookup-context.xml"/>

<!-- Auto-Wiring: 按类型注入 -->
<bean id="userRepository" class="org.thinging.in.spring.ioc.overview.repository.UserRepository" autowire="byType">
</bean>

dependency-lookup-context.xml:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

<!--    <context:annotation-config/>-->

<!--    <context:component-scan base-package="org.acme" />-->

    <!-- Root BeanDefinition 不需要合并,不存在 parent -->
    <!-- 普通 beanDefinition GenericBeanDefinition -->
    <!-- 经过合并后 GenericBeanDefinition 变成 RootBeanDefinition -->
    <bean id="user" class="org.geekbang.thinking.in.spring.ioc.overview.domain.User">
        <property name="id" value="1"/>
        <property name="name" value="小马哥"/>
        <property name="city" value="HANGZHOU"/>
        <property name="workCities" value="BEIJING,HANGZHOU"/>
        <property name="lifeCities">
            <list>
                <value>BEIJING</value>
                <value>SHANGHAI</value>
            </list>
        </property>
        <property name="configFileLocation" value="classpath:/META-INF/user-config.properties"/>
    </bean>

    <!-- 普通 beanDefinition GenericBeanDefinition -->
    <!-- 合并后 GenericBeanDefinition 变成 RootBeanDefinition,并且覆盖 parent 相关配置-->
    <!-- primary = true , 增加了一个 address 属性 -->
    <bean id="superUser" class="org.geekbang.thinking.in.spring.ioc.overview.domain.SuperUser" parent="user"
          primary="true">
        <property name="address" value="杭州"/>
    </bean>

    <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
        <property name="targetBeanName" value="user"/>
    </bean>
</beans>

在这个例子中,我们通过 XML 配置文件导入了 dependency-lookup-context.xml,并配置了一个名为 userRepositoryUserRepository Bean,并通过 autowire=“byType” 实现了自动按类型注入。这样,Spring 容器会在运行时查找并注入与 UserRepository 类型匹配的 User 对象。

UserRepository 类

代码语言:javascript
复制
public class UserRepository {

    /**
     * 自定义Bean
     */
    private Collection<User> users;

    public Collection<User> getUsers() {
        return users;
    }

    public void setUsers(Collection<User> users) {
        this.users = users;
    }
}

UserRepository 类中定义了一个名为 users 的集合属性,并提供了相应的 Getter 和 Setter 方法。通过 Setter 方法,我们可以在 Spring 容器中配置的时候注入一组 User 对象。

主程序

代码语言:javascript
复制
public static void main(String[] args) {
    // 配置 XML 配置文件
    // 启动 Spring 应用上下文
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
    UserRepository userRepository = beanFactory.getBean("userRepository", UserRepository.class);
    System.out.println(userRepository.getUsers());
}

在主程序中,我们通过 ClassPathXmlApplicationContext 加载了 XML 配置文件,获取了名为 userRepositoryUserRepository Bean,并输出了其中包含的 User 对象集合。

结论

通过这个简单的示例,我们了解了 Spring Framework 中依赖注入的基本原理。依赖注入通过控制反转容器实现,使得应用程序中的对象不再负责管理自己的依赖关系,而是由 IoC 容器负责。这种设计模式降低了组件之间的耦合度,提高了代码的可测试性和可维护性,是 Spring 成功的关键之一。在实际项目中,我们可以根据需求选择适合的依赖注入方式,使代码更加清晰、灵活且易于维护。

后续内容文章持续更新中…

近期发布。


关于我

👋🏻你好,我是Debug.c。微信公众号:种颗代码技术树 的维护者,一个跨专业自学Java,对技术保持热爱的bug猿,同样也是在某二线城市打拼四年余的Java Coder。

🏆在掘金、CSDN、公众号我将分享我最近学习的内容、踩过的坑以及自己对技术的理解。

📞如果您对我感兴趣,请联系我。

若有收获,就点个赞吧,喜欢原图请私信我。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-11-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • theme: smartblue
  • 什么是依赖注入?
  • Spring 中的依赖注入
    • 构造函数注入的案例:
      • Setter 方法注入的案例:
      • UserRepository 类
      • 主程序
      • 结论
      • 后续内容文章持续更新中…
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档