就我的口味而言,野外注射有点“遥不可及”。
考虑一下您在Google网上论坛帖子中提供的示例:
public class VeracodeServiceImplTest {
@Tested(fullyInitialized=true)
VeracodeServiceImpl veracodeService;
@Tested(fullyInitialized=true, availableDuringSetup=true)
VeracodeRepositoryImpl veracodeRepository;
@Injectable private ResultsAPIWrapper resultsApiWrapper;
@Injectable private AdminAPIWrapper adminApiWrapper;
@Injectable private UploadAPIWrapper uploadApiWrapper;
@Injectable private MitigationAPIWrapper mitigationApiWrapper;
static { VeracodeRepositoryImpl.class.getName(); }
...
}
因此,基本上,您要说的是:“我有一个带有私有状态的类,并在其中附加了@injectable
注释,这意味着即使我的状态已全部声明为私有,状态也可以由外部的某些代理自动填充。 ”
我了解这样做的动机。这是为了避免正确设置班级所固有的许多仪式。基本上,人们的意思是“我已经厌倦了编写所有这些样板,因此我将注释所有状态,然后让DI容器负责为我设置它。”
这是完全正确的观点。但这也是可以避免的语言功能的解决方法。另外,为什么要停在那里?传统上,DI依赖于每个具有配套接口的类。为什么不消除所有带有注解的接口呢?
考虑替代方案(它将是C#,因为我更了解它,但是Java中可能有一个完全等效的方案):
public class VeracodeService
{
private readonly IResultsAPIWrapper _resultsApiWrapper;
private readonly IAdminAPIWrapper _adminApiWrapper;
private readonly IUploadAPIWrapper _uploadApiWrapper;
private readonly IMitigationAPIWrapper _mitigationApiWrapper;
// Constructor
public VeracodeService(IResultsAPIWrapper resultsApiWrapper, IAdminAPIWrapper adminApiWrapper, IUploadAPIWrapper uploadApiWrapper, IMitigationAPIWrapper mitigationApiWrapper)
{
_resultsAPIWrapper = resultsAPIWrapper;
_adminAPIWrapper = adminAPIWrapper;
_uploadAPIWrapper = uploadAPIWrapper;
_mitigationAPIWrapper = mitigationAPIWrapper;
}
}
我已经知道了这堂课的一些知识。这是一门不变的课。状态只能在构造函数中设置(在这种情况下为引用)。而且由于所有内容都源自接口,因此我可以交换构造函数中的实现,这就是您的模拟输入的来源。
现在,我的DI容器所需要做的就是对构造函数进行反思,以确定需要更新哪些对象。但是,这种反思是以一流的方式对公众成员进行的。也就是说,元数据已经在构造函数中声明了该类的一部分,该方法的明确目的是为类提供所需的依赖项。
当然,这是很多样板,但这是语言的设计方式。注释似乎是对本应内置在语言本身中的东西的肮脏hack。