【问题标题】:How does class gets injected which implements interface method being called in Java or Groovy code?如何注入实现在 Java 或 Groovy 代码中调用的接口方法的类?
【发布时间】:2020-10-24 16:14:29
【问题描述】:

我有以下来自 Spring 框架项目的 groovy 代码:

import org.springframework.oxm.Unmarshaller

public class ItemSearchService  {
    Unmarshaller unmarshaller;
    public ItemSearchResponse getObject(InputStream xml) {
    
        ItemSearchResponse its = null;
        try {
            its = (ItemSearchResponse) unmarshaller.unmarshal(new StreamSource(xml));
        } finally {
        }
        return its;
    }
}

Unmarshaller.unmarshall 实际上是接口方法: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/oxm/Unmarshaller.html

Unmarshaller 接口由多个类实现。

谁决定在运行时注入哪个实现类以及它如何决定使用哪个类?

Spring IoC 机制能做到这一点吗?如果是这样,它是在生成 jar 时在构建时选择一个特定的实现类,还是在运行时选择一个特定的实现类?

还有如何知道它实际使用的是哪个实现类?

假设类路径中有依赖的 jar,上述代码是否可以在 Spring 之外的普通 Java 文件中工作?

【问题讨论】:

  • 你确定这是一个 Groovy 类?它是有效的,但它非常符合 Java 风格。对于您的一般问题,它可能使用 setter 注入,是的,Spring 容器将确定要提供的特定对象,但我希望看到 @Autowired 用于基于 setter 的属性。跨度>
  • 是的,它来自基于 Spring 的 Grails 项目的 groovy 类。

标签: java spring grails groovy


【解决方案1】:

一旦涉及 Grails 项目(不是纯 Spring 项目),就应该澄清一些事情。

谁决定在运行时注入哪个实现类以及它如何决定使用哪个类? Spring IoC 机制可以做到这一点吗?如果是这样,它是在生成 jar 时在构建时选择一个特定的实现类,还是在运行时选择一个特定的实现类?

@svr 的答案和 Internet 上的其他文档很好地描述了 Spring 在普通 Spring(Boot) 中的作用,但与您的情况没有太大关系。

在 Grails 中使用约定优于配置的原则,这意味着

  • 默认情况下 Bean 自动装配处于活动状态
  • 只有被声明为 Grails 人工制品的 bean,例如 Service,会被自动注入。

通常,如果你想自动装配其他原型的 bean,你必须在某个地方声明它,否则 Grails 中的 Spring IoC 容器根本找不到它。

您应该检查您的grails-app/conf/spring 文件夹中的resources.groovy(或者可能是yaml 或xml 文件,具体取决于版本),并查看您的unmarshaller bean 是否在那里定义。它应该看起来像:

beans = {
  unmarshaller Unmarshaller ....
}

所以,基本上所有项目的 jar 文件中有多少个 Unmarshaller 接口的实现并不重要。唯一重要的是您的 resources.groovy 中定义的内容。

如果你想在运行时检查 bean 的类,只需在你的服务中记录它的类:

class ItemSearchService  {
  Unmarshaller unmarshaller
  ItemSearchResponse getObject(InputStream xml) {
     log.info "unmarshaller's class is $unmarshaller.class"
     // or
     // println "unmarshaller's class is $unmarshaller.class"
  }
}  

【讨论】:

    【解决方案2】:

    谁决定在运行时注入哪个实现类以及如何注入 它决定使用哪个类? Spring IoC 机制可以做到这一点吗?如果是这样,它会捡起一个 生成 jar 时构建时的特定实现类或 它在运行时执行吗?

    是的 Spring IOC 容器。它发生在应用程序运行时的运行时。

    还有如何知道它实际使用的是哪个实现类?

    在大多数情况下,您必须定义 bean 并选择实现。对于其他情况,您可以查看 spring 自动配置类。

    上面的代码是否可以在 Spring 之外的普通 Java 文件中工作,假设 类路径中的依赖 jars?

    不确定你在 Spring 之外的意思,但只要应用程序被正确打包,它应该可以工作。

    快速概览

    Spring IOC 只会在应用程序上下文中找到一个 bean。应用程序上下文松散地是 bean 的存储库。

    类路径扫描和注册

    Spring 扫描应用程序以获取所有原型类并将 bean 定义注册到应用程序上下文中。刻板注解包括@Component、@Repository、@Service、@Controller、@Configuration。 More

    依赖注入

    Spring DI 创建 bean 并将它们作为依赖项注入到应用程序中。您可以使用注册的 bean 在不同的应用程序组件之间创建依赖关系,spring 将为您自动装配这些。 More。有两种类型的 DI - 基于构造函数和基于 setter - 构造函数用于必需依赖项,而基于 setter 用于可选依赖项。 More

    当您使用任何 spring 类时,都会提供合理的默认值。您只需要定义没有默认值的 bean,或者您想选择不同的实现。通过使用 Spring Boot Auto Configuration 可以进一步丰富应用程序上下文,其中所有相关的类被连接在一起以形成一个连贯的入口类。然后,您可以轻松地将它们注入应用程序以开始使用。 More

    示例

    您可以在 @Configuration 类中为 Web 服务模块定义 bean。

    @Configuration
    public class WSConfig {
       @Bean
       public Jaxb2Marshaller marshaller() {
          Jaxb2Marshaller marsharller = new Jaxb2Marshaller();
          marsharller.setContextPath("some package");
       }
    
       @Bean
       public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marsharller) {         
          WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marsharller);
       }
    }
    
    @RequiredArgsConstructur
    public class ItemSearchService  {
        private final Unmarshaller unmarshaller;
        public ItemSearchResponse getObject(InputStream xml) {
           ItemSearchResponse its = null;
           try {
            its = (ItemSearchResponse) unmarshaller.unmarshal(new StreamSource(xml));
            } finally {}
           return its;
        }
     }
    

    WebServicesAutoConfiguration 会自动处理类似的配置,并在使用 Spring Boot 时提供自定义方式。

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 2014-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多