autowiring接口与类

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

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

juud5qan

juud5qan1#

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

  1. public interface I{
  2. void doSomething();
  3. }
  4. @Component("a")
  5. public class A implements I{
  6. public void doSomething(){
  7. //...
  8. }
  9. public void doSomethingElse(){
  10. //...
  11. }
  12. }
  13. @Component("b")
  14. public class B implements I{
  15. public void doSomething(){
  16. //...
  17. }
  18. }

如果你使用

  1. @Autowired
  2. private A yourVariable;

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

  1. @Qualifier("a")
  2. private I yourVariable;

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

展开查看全部
dba5bblo

dba5bblo2#

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

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

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

  1. @Component
  2. public class Driver {
  3. @Autowired
  4. private IImpl1 i;
  5. }

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

  1. @Component
  2. public class Driver {
  3. @Autowired
  4. @Qualifier("someLogicalName") // under the hood it spring will map it to IImpl1 but you don't know that here
  5. I i;
  6. }

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

  1. @Configuration
  2. public class MyConfiguration {
  3. @Bean
  4. public Driver driver(@Qualifier("someLogicalName") I i) {
  5. return new Driver(i);
  6. }
  7. }
  8. public class Driver {
  9. private final I i;
  10. public Driver(I i) { // in real life this constructor can be generated by
  11. // lombok or something, put it here for the sake of completeness
  12. this.i = i;
  13. }
  14. }

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

展开查看全部

相关问题