Spring依赖注入(DI)针对接口的实现

11

我已经观看了一些关于Spring依赖注入和MVC的教程,但我似乎仍然不理解如何具体实例化类?

我的意思是,例如如果我有一个变量

@Autowired
ClassA someObject;

我该如何让Spring创建一个ClassB的实例作为ClassA的子类,例如:someObject = new ClassB();

我并不完全理解Spring是如何工作的,是ContextLoaderListener自动完成这个过程还是我们需要创建某种类型的配置类来指定Spring应该将这些类实例化为什么样的对象?(在教程中我没有看到这方面的内容)如果是的话,我们该如何进行指定,并且具体是什么样的流程?我们如何将它配置到web.xml中等等?

4个回答

33
你可以这样做:
接口:
package org.better.place

public interface SuperDuperInterface{
    public void saveWorld();
}

实现:

package org.better.place

import org.springframework.stereotype

@Component
public class SuperDuperClass implements SuperDuperInterface{
     public void saveWorld(){
          System.out.println("Done");
     }
}

客户:

package org.better.place

import org.springframework.beans.factory.annotation.Autowire;

public class SuperDuperService{
       @Autowire
       private SuperDuperInterface superDuper;


       public void doIt(){
           superDuper.saveWorld();
       }

}

现在你已经定义了接口,编写了实现并将其标记为组件 - 这里的文档。现在唯一剩下的就是告诉Spring在哪里找到组件,以便它们可以用于自动装配。

<beans ...>

     <context:component-scan base-package="org.better.place"/>

</beans>

你不能使用注解来标记基于构造函数的bean。要么使用带有自动装配依赖项的默认构造函数,要么使用基于Java/XML的配置(删除@Component注解和context:component-scan元素)。详细信息请参阅此处的帖子:http://www.javalobby.org/java/forums/t18396.html - Stefan
还有人在阅读这个帖子吗?我的问题是 - 如果不使用@Autowired,你会如何实现相同的功能? - user1414745
8
好的,如果我们有多个实现,你会如何进行自动装配?因为你是在服务层进行自动装配,对吗?我试图直接自动装配实现,但失败了。您能解释一下吗?先谢谢! - PavanSandeep
@PavanSandeep 如果您有多个接口实现,您需要使用@Qualifier注释(参见https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-autowired-annotation-qualifiers):给定2个接口实现,每个实现都得到一个带有唯一限定符的类级别注释,例如第一个实现的`@Qualifier("interfaceImpl1")`和第二个实现的 @Qualifier("interfaceImpl2")。声明接口为依赖项的类使用@Qualifier(...)注释来标识实现。 - JCvanDamme
我想如果只有其中一个实现被@ Component修饰,那么拥有多个实现应该是可以的吧?就像在大多数情况下,您会有Mock类和Regular类,并且您将手动注入Mock类,因此不需要装饰器,对吗? - aurelia
显示剩余2条评论

1
在 applicationContext.xml 文件中,您必须指定要创建对象的类的类型,或者如果您正在使用最新版本的 Spring,则可以直接对该类进行任何一个注释:@Component@Service@Repository。如果您正在使用基于 XML 的配置,则在 web.xml 中,您必须将 XML 文件的路径指定为 servlet 的 context-param。

好的,假设我只需要在ClassB上使用Component注解,Spring就会自动为我实例化一个新的ClassB()对象?如果同时将ClassA和ClassB都用Component注解标注,那么Spring会怎么处理呢?我的理解正确吗? - Arturas M
1
如果两者都被注释为@Component,则在自动装配时,您将需要使用Qualifier注释,该注释指示Spring注入与您提供的限定符名称匹配的bean。 - Sumit Desai
1
如果这是一个常见的情况,也可以考虑使用XML描述符。 - sorencito

0

0

最佳实践

@RestController
@RequestMapping("/order")
public class OrderController {
    private final IOrderProducer _IOrderProducer;

    public OrderController(IOrderProducer iorderProducer) {
        this._IOrderProducer = iorderProducer;
    }

    @GetMapping("/OrderService")
    void get() {
        _IOrderProducer.CreateOrderProducer("This is a Producer");
    }
}

接口

@Service
public interface IOrderProducer {
    void CreateOrderProducer(String message);
}

实现

public class OrderProducer implements  IOrderProducer{
    private KafkaTemplate<String, String> _template;

    public OrderProducer(KafkaTemplate<String, String> template) {
        this._template = template;
    }

    public void CreateOrderProducer(String message){
        this._template.send("Topic1", message);
    }
}

您需要在Spring Boot中包含Project Lombok依赖项

Gradle implementation 'org.projectlombok:lombok'


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接