Java Spring如何将类与接口解耦?

Java Spring如何将类与接口解耦?,java,spring,spring-mvc,dependency-injection,decoupling,Java,Spring,Spring Mvc,Dependency Injection,Decoupling,在Spring框架的官方网站上,有一个例子展示了Spring是如何将类与接口解耦的,或者更确切地说,是如何将实现与接口解耦的 代码如下: 接口: package hello; public interface MessageService { String getMessage(); } 组件类别: package hello; import org.springframework.beans.factory.annotation.Autowired; import org.spr

在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
能正常工作吗


关于

是的,您的上下文中必须有一个
MessageService
。如果没有它,由
@Autowired
注释引起的依赖项注入将在上下文初始化期间失败

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

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


如果您碰巧拥有
messageserviceinmpl1
,然后将其更改为
messageserviceinmpl2
MessagePrinter
将完全不需要更改(当然,如果两个实现在契约方面表现相同)。

我想您正在寻找
@限定符
,请参阅@ElliottFrisch我不知道什么是
@限定符
。我刚开始学习spring,示例在网站的第一页。我无法理解
MessagePrinter
是如何与
MessageService
的实现脱钩的,请单击我提供的链接。在示例代码中,
MessagePrinter
如何与特定的
MessageService
绑定?请注意
@Autowired
注释。“这就是为什么!”艾略特·弗里希说,“我太糊涂了!你是什么意思?您的意思是
MessagePrinter
如何依赖于
MessageService
?!!让我问一个问题,术语解耦,是否意味着
MessagePrinter
不再需要
MessageService
的实现?如果没有,那我还没明白呢!这并不意味着。这意味着它没有耦合(绑定、链接、硬编码使用)到特定的实现;您可以将一个
MessageService
替换为
MessageService
的任何其他实现。或者像您的示例中那样模拟
MessageService
。谢谢。但是我在没有使用Spring的情况下读到,
MessagePrinter
依赖于
MessageService
的一些实现。春天只是让它不可能发生。所以我的问题仍然是一致的。通过使用接口(
MessageService
),您已经与它的实现解耦了。测试很简单:
MessageService
知道实现的任何信息吗?答案是‘不’(你甚至都没有!)。要实现这一点,您只需使用接口编程并使用依赖项注入。Spring不是一个需求(尽管它允许通过为您构建应用程序上下文轻松地使用此模式)。
mockMessageService()
是否是Spring的一部分?Spring是一个框架。在本例中,我相信您指的是SpringIoC容器,它从您的
@Configuration
-注释类构建应用程序上下文,并注入依赖项
mockMessageService()
是一种为该上下文生成
MessageService
实例的方法;它是应用程序的一部分,而不是Spring的一部分。