Полевая инъекция - это слишком «жуткое действие на расстоянии», на мой вкус.
Рассмотрим пример, который вы предоставили в своем посте групп 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-контейнер, - это размышлять над конструктором, чтобы определить, какие объекты ему нужны для создания нового. Но это размышление делается на публичного члена, первоклассным способом; т. е. метаданные уже являются частью класса, поскольку они были объявлены в конструкторе, методе, целью которого является предоставление классу необходимых ему зависимостей.
Конечно, это много шаблонно, но именно так и был разработан язык. Аннотации кажутся грязным хаком для того, что должно было быть встроено в сам язык.