2017-09-27 9 views
1

我正在開發Spring Boot應用程序並使用Mybatis。爲了確保由Mybatis實例化的對象的不變性,我讓Mybatis使用<constructor>而不是使對象變爲可變的setter。像其他序數對象一樣,這些Mybatis實例化的對象需要依賴來完成它們的職責,而這些依賴有時是由Spring實例化的bean。我應該如何注入依賴到由Mybatis實例化的不可變域對象?

如果一個對象被Spring實例化,那麼很容易爲它注入依賴關係。但是顯然,由Mybatis實例化的對象不在Spring的DI容器中,並且不能使用@Autowired或其他Spring機制來注入它的依賴關係。

課程,由MyBatis的實例後手動我可以注入的依賴關係,如:

DomainA d = DomainAMapper.fetchOne(); 
d.setDependency(dependency); 

但是,這打破了DomainA不變性。

我該如何滿足我的需求,即在保持其不可變性的同時將依賴項注入到Mybatis實例化對象?

+0

你可以分享你想管理的相同的例子「依賴關係」嗎?例如,告訴我一些DomainA中的依賴關係。 – Rafa

+0

@Rafa感謝您的評論。我的意思是這裏的依賴關係是在DomainA類中使用的其他類。在我目前的情況下,它是用C++編寫的用於處理機器學習事情的本地模塊的Java包裝類。我想注入它以使單元測試更容易。 – umainyosu

回答

1

如果您對當前的設計非常滿意,並且您專注於測試,那麼PowerMockit應該滿足您的需求,因爲它能夠「設置/模擬」私人成員。

實施例:

@Component 
public class DomainA { 
    @Autowired 
    private ApplicationContext context; 
    public boolean isContextInitilized() { 
     return context != null; 
    } 
} 

import org.powermock.api.support.membermodification.MemberModifier; 
...  
@RunWith(SpringRunner.class) 
@SpringBootTest 
public class DemoApplicationTests { 
    @Autowired 
    ApplicationContext contextToInject; 
    @Autowired 
    DomainA domainAAutowired; 

    @Test 
    public void contextLoads() throws IllegalArgumentException, IllegalAccessException { 
     // Autowired spring beans work fine 
     assertTrue(domainAAutowired.isContextInitilized()); 
     // Class out of spring context won't initialize dependencies 
     DomainA domainOutOfSpringContext = new DomainA(); 
     assertFalse(domainOutOfSpringContext.isContextInitilized()); 
     // We can 'set' private members using PowerMock 
     MemberModifier.field(DomainA.class, "context").set(domainOutOfSpringContext, contextToInject); 
     assertTrue(domainOutOfSpringContext.isContextInitilized()); 
    } 
} 

在一個側面說明,MyBatis的類被認爲是簡單的POJO。在MyBatis中有彈簧依賴性可能是一個糟糕的問題分離指標,因爲它們應該只關注持久層。

+0

非常感謝您的回答。而你的觀點是「在MyBatis中有Spring依賴關係可能是一個糟糕的問題分離指標,因爲他們應該只關注持久層」對我來說真的很有意義。但從這個意義上說,Mybatis生成的對象是否只有getter和setter,並將邏輯轉移到其他類?你有什麼想法,我們可以如何避免[貧血域模型](https://www.martinfowler.com/bliki/AnemicDomainModel.html)? – umainyosu

+1

認爲MyBatis接口爲'Repositories'和MyBatis類爲'Entities'。然後創建一個「服務」層,這是一個更自然的地方來包含春天的依賴。 「服務」層應該很薄,但能夠委託給其他資源。您還可以將「服務」圖層想象爲您的資源的「外觀」。 – Rafa

+0

再次感謝您的回答。 '服務層應該很薄,但能夠委託給其他資源'。那麼這個邏輯流程能成爲一個可能的例子嗎? 1)服務類調用存儲庫以從數據庫中獲取實體,2)服務類調用一些工廠來實例化包含獲取的實體的域對象,3)服務類調用域對象的方法來執行業務邏輯。 – umainyosu

相關問題