2017-09-27 11 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

相关问题