【问题标题】:How does Spring decouple a class from an interface?Spring 如何将类与接口解耦?
【发布时间】:2018-07-21 22:08:03
【问题描述】:

在Spring框架的官方网站上,有一个例子展示了Spring如何将类与接口解耦,或者更好的说,如果是接口,则为实现。

代码如下:

界面:

package hello;

public interface MessageService {
    String getMessage();
}

组件类:

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MessagePrinter {

    final private MessageService service;

    @Autowired
    public MessagePrinter(MessageService service) {
        this.service = service;
    }

    public void printMessage() {
        System.out.println(this.service.getMessage());
    }
}

应用:

package hello;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan
public class Application {

    @Bean
    MessageService mockMessageService() {
        return new MessageService() {
            public String getMessage() {
              return "Hello World!";
            }
        };
    }

  public static void main(String[] args) {
      ApplicationContext context = 
          new AnnotationConfigApplicationContext(Application.class);
      MessagePrinter printer = context.getBean(MessagePrinter.class);
      printer.printMessage();
  }
}

我目前对依赖注入的理解是,当一个名为 A 的类需要另一个名为 B 的类来处理它必须执行的任何操作时,B 是一个依赖项,A 是一个依赖项。如果B 是一个接口,那么A 依赖于B一些 实现。

那么,在上面的代码中,MessagePrinter 如何与MessageService 实现解耦?

我们还是要实现MessageService,如果不实现,MessagePrinter能正常工作吗?

问候

【问题讨论】:

  • 我想你在找@Qualifier,见Autowiring spring bean by name using annotation
  • @ElliottFrisch 我不知道@Qualifier 是什么。我刚开始学习spring,例子在网站的第一页。我不明白MessagePrinter 是如何与MessageService 的实现分离的
  • 点击我提供的链接。在您的示例代码中,如何 MessagePrinter 绑定特定 MessageService?注意@Autowired 注释。就是这样。
  • @ElliottFrisch 我很困惑!你是什​​么意思?你的意思是MessagePrinter 是如何依赖于MessageService 的?!!让我问一个问题,术语decoupling,是不是意味着MessagePrinter 不再需要MessageService 的实现了?如果不是,那我还没看懂!
  • 不是的意思。这意味着它没有与特定实现耦合(绑定、链接、硬编码);您可以将MessageService 替换为MessageService 的任何其他实现。或模拟MessageService,如您的示例。

标签: java spring spring-mvc dependency-injection decoupling


【解决方案1】:

是的,您的上下文中必须有 MessageService。没有它,@Autowired 注解导致的依赖注入在上下文初始化时会失败。

如果我正确理解术语,MessagePrinter 不能与 MessageService 分离,因为前者在其代码中直接使用后者。但它可以与MessageService 实现解耦。

它与MessageService实现解耦,因为它只依赖于MessageService接口;它对实现类一无所知。

如果您碰巧拥有MessageServiceImpl1,然后将其更改为MessageServiceImpl2,则根本不必更改MessagePrinter(当然,如果两个实现在合同方面表现相同)。

【讨论】:

  • 谢谢。但是我在没有使用 Spring 的情况下阅读过 MessagePrinter IS 依赖于 MessageService 的某些实现。春天只是使它可能不会发生。所以我的问题还是一致的。
  • 通过使用接口 (MessageService),您已经从它的实现中解耦了。测试很简单:MessageService 对实现有任何了解吗?答案是“不”(你甚至没有它们!)。为此,您只需使用接口进行编程并使用依赖注入。 Spring 不是必需的(尽管它允许通过为您构建应用程序上下文来轻松使用此模式)。
  • 我很困惑。 mockMessageService() 是 Spring 的一部分吗?
  • Spring 是一个框架。在这种情况下,我相信您的意思是 Spring IoC 容器,它从您的 @Configuration-annotated 类构建应用程序上下文并注入依赖项。 mockMessageService() 是为此上下文生成 MessageService 实例的方法;它是应用程序的一部分,而不是 Spring 的一部分。
猜你喜欢
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 2011-09-19
  • 2012-01-23
  • 1970-01-01
  • 2020-07-22
  • 2015-07-21
  • 1970-01-01
相关资源
最近更新 更多