Spring Best practice for Dependency Injection

我的未来我决定 提交于 2020-01-30 08:39:49

问题


I have some confusion about DI in spring

public interface A{
    void methodA();
}
public class AImpl implements A{
    public void methodA(){
          // todo something
    }
}

public interface B{
    void methodB();
}
public class BImpl implements B{
     public void methodB(){
       //todo somethong
     }
}

I have two interface A and B and 2 class implements it. So, I have 2 Class that implement interface C, it depend on Interface A and B

This is case 1:

public interface C{
    void methodC();
}

public class CAutowired implements C{
    @Autowired
    private A a;
    @Autowired
    private B b;

    public void methodC(){
       a.methodA();
       b.methodB();
    }
}

File .xml config

  <beans>
       <bean id="classA" class="com.example.AImpl" />
       <bean id="classB" class="com.example.BImpl" />
       <bean id="classC" class="com.example.CAutowired" />
    <beans>

In this case, i have a question: - How to Mock A and B when i write unitTest for class CAutowired

This is case 2:

public class CInitInject implements C{
    private A a;
    private B b;

    public CInitInject(A a, B b){
       this.a = a;
       this.b = b;
    }

    public void methodC(){
       a.methodA();
       b.methodB();
    }
}

File .xml config

  <beans>
       <bean id="classA" class="com.example.AImpl" />
       <bean id="classB" class="com.example.BImpl" />
       <bean id="classC" class="com.example.CInitInject">
             <constructor-arg ref="classA" />
             <constructor-arg ref="classB" />
       </bean>
    <beans>

In this case, i get DI method the same in .NET. I can Mock A and B by inject into constructor. Example:

@Mock
private A aMock;
@Mock
private B bMock;

private C c;

public void setUp(){
   c = new CInitInject(aMock, bMock);
}

@Test
public void test(){
   // todo Test somemethod
}

End of all, I have a question

  1. What is best practice between case 1 and case 2?
  2. How to Mock it when unit test

回答1:


(1)

It is customary today to inject beans into the constructor.

It is considered the best practice because it strictly informs users of the class (in this case, users of CInitInject) what is expected for this class in order for it to do its job properly. The users don't have to guess which dependencies are expected as happens with setters.

(1.1)

Your code sample for "case 1" is bundling two code stylings, and you might want to avoid that.

It is common to choose between annotation driven coding and XML.

For that case, should you have chosen to use annotations, your code would have looked like this (notice no XML is involved):

public interface C{
    void methodC();
}

@Bean(name="a")
public class AImpl implements A{
    public void methodA(){
        // todo something
    }
}

@Bean
public class CAutowired implements C{
    @Autowired
    private A a;
    @Autowired
    private B b;

    public void methodC(){
       a.methodA();
       b.methodB();
    }
}

See example of how to use the helping code to make this work.

(1.2)

Should you choose to use annotation-driven coding, here's an example of injecting beans into the constructor:

@Bean
public class CAutowired implements C {
    private A a;
    private B b;

    @Autowired
    public CAutowired(A a, B b) {
        this.a = a;
        this.b = b;
    }
}

(1.3)

It is also common to avoid hard-wiring Spring so much into your system, when using annotations. Therefore, some people create classes that are aware of both spring and other classes (such as CAutowired that would now be renamed to CImpl) and only they use @Autowired and @Bean annotations. Example:

//just an example, you'll think of how this works for YOU
public class OneOfSomeSpringManagers {
    public OneOfSomeSpringManagers() {
        C c = getC(getA());
    }

    @Bean
    public A getA() {
        ...
    }

    ...
}

(2)

Use Mockito to mock the injected dependencies in unit tests.



来源:https://stackoverflow.com/questions/38136164/spring-best-practice-for-dependency-injection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!