autowiring接口与类

xqkwcwgp  于 2021-07-15  发布在  Java
关注(0)|答案(2)|浏览(373)

如果一个接口有多个实现,那么我必须使用@qualifier来指示要自动连接的类。直接自动连接类而不是接口不是更有意义吗?

juud5qan

juud5qan1#

这就是面向对象编程(尤其是抽象和多态)的意义所在。
构建独立于具体实现的类并使用接口。
这允许您随时更改所使用的实现。
假设你有:

public interface I{
    void doSomething();
}

@Component("a")
public class A implements I{
    public void doSomething(){
        //...
    }
    public void doSomethingElse(){
        //...
    }
}
@Component("b")
public class B implements I{
    public void doSomething(){
        //...
    }
}

如果你使用

@Autowired
private A yourVariable;

你可能会想用 doSomethingElse() 方法的实现细节(无论出于什么原因)。
但是,如果您使用

@Qualifier("a")
private I yourVariable;

这不能发生,因为接口中不存在该方法。
这使您能够随时交换实现。

dba5bblo

dba5bblo2#

直接自动连接类而不是接口不是更有意义吗?
这在很大程度上取决于如何准确地使用限定符,但一般来说,答案是“否”,如果您有一个接口,则自动连接类是一件不好的事情-您应该始终按接口工作。
以下是示例:

interface I { void foo(); }
class IImpl1 implements I { 
  void foo() {System.out.println("Impl1");  
  pubic void bar() {// another method - why not?}
}
class IImpl2 implements I { void foo() {System.out.println("Impl2"); }

注意,一个实现 IImpl1 有一个附加方法 bar 它不属于接口 I 案例1:

@Component
public class Driver {
    @Autowired
    private IImpl1 i;
}

这里的类驱动是紧紧可以实现的 IImpl1 一般来说,我可以调用 barDriver 类,因为我有这个实现,但在这种情况下,如果我必须切换 Driver 将来您还必须更改代码:既要更改引用,又要去掉对的调用 IImpl1.bar() 这可能没那么容易做到——这是逻辑上的改变。结果,整个多态行为丢失了。
到目前为止,这是最糟糕的编程方式。
现在,考虑案例2:

@Component
public class Driver {

   @Autowired
   @Qualifier("someLogicalName") // under the hood it spring will map it to IImpl1 but you don't know that here
   I i;
}

在这种情况下——情况要好得多——您永远不会在代码级别将驱动程序与具体实现耦合。这意味着一般来说,更改限定符以获得另一个实现就足够了。你不能打电话 bar 再也不能编译了。您也不知道将注入什么实现。如果将来实际实现“somelogicalname”逻辑的组件的实现将发生变化(我的意思是您将创建一个新类) IImpl3 ),您在这里感觉不到它-您将把限定符放在新类上,所有使用它的地方都将自动获得该实现。
案例3:

@Configuration
public class MyConfiguration {

   @Bean
   public Driver driver(@Qualifier("someLogicalName") I i) {
       return new Driver(i);
   }
}

public class Driver {
   private final I i;

   public Driver(I i) { // in real life this constructor can be generated by 
                        // lombok or something, put it here for the sake of completeness
     this.i = i;
   }
}

到目前为止,这是最“干净”的方法——从概念上讲,它与案例2非常相似,但是在本例中,您没有将限定符放在 Driver 上课,其实是上课 Driver 甚至在代码/元数据级别上都不知道它与spring有关。当然,案例2的所有“优点”在这里也同样适用。

相关问题