Ответ 1
Нет... нет эквивалента для необязательного в JSR 330... если вы хотите использовать опциональную инъекцию, вам придется придерживаться аннотации @Autowired
Spring @Autowire
может быть сконфигурирован таким образом, что Spring не будет вызывать ошибку, если не найдено подходящих кандидатов на автоуверсию: @Autowire(required=false)
Есть ли эквивалентная аннотация JSR-330? @Inject
всегда терпит неудачу, если нет подходящего кандидата. Есть ли способ, которым я могу использовать @Inject
, но не иметь фреймворка, если не найдены соответствующие типы? В такой степени я не смог найти документацию.
Нет... нет эквивалента для необязательного в JSR 330... если вы хотите использовать опциональную инъекцию, вам придется придерживаться аннотации @Autowired
Я очень удивлен, что никто не упомянул java.util.Optional
.
Если вы используете Java 8, а версия Spring - 4.1
или выше (см. здесь), вместо
@Autowired(required = false)
private SomeBean someBean;
Вы можете просто использовать класс java.util.Optional
, который поставляется с Java 8. Используйте его как:
@Inject
private Optional<SomeBean> someBean;
Этот экземпляр никогда не будет null
, и вы можете использовать его как:
if (someBean.isPresent()) {
// do your thing
}
Таким образом, вы также можете выполнить инсталляцию конструктора, с некоторыми требуемыми beans и некоторыми beans, дает большую гибкость.
Примечание. К сожалению, Spring не поддерживает Guava com.google.common.base.Optional
(см. здесь), поэтому этот метод будет работать, только если вы используют Java 8 (или выше).
AutowiredAnnotationBeanFactoryPostProcessor
(Spring 3.2) содержит этот метод, чтобы определить, требуется ли поддерживаемая аннотация "Autowire" или нет:
/**
* Determine if the annotated field or method requires its dependency.
* <p>A 'required' dependency means that autowiring should fail when no beans
* are found. Otherwise, the autowiring process will simply bypass the field
* or method when no beans are found.
* @param annotation the Autowired annotation
* @return whether the annotation indicates that a dependency is required
*/
protected boolean determineRequiredStatus(Annotation annotation) {
try {
Method method = ReflectionUtils.findMethod(annotation.annotationType(), this.requiredParameterName);
if (method == null) {
// annotations like @Inject and @Value don't have a method (attribute) named "required"
// -> default to required status
return true;
}
return (this.requiredParameterValue == (Boolean) ReflectionUtils.invokeMethod(method, annotation));
}
catch (Exception ex) {
// an exception was thrown during reflective invocation of the required attribute
// -> default to required status
return true;
}
}
Короче говоря, нет, но не по умолчанию.
Имя метода, которое ищет по умолчанию, является "обязательным", которое не является полем в аннотации @Inject
, таким образом, method
будет null
и true
будет возвращено.
Возможно, вы сможете изменить это, подклассифицируя этот BeanPostProcessor
и переопределяя метод determineRequiredStatus(Annotation)
, чтобы вернуть true, или, вернее, что-то "умнее".
Можно создать дополнительную точку инъекции!
Вам нужно использовать поиск инъекций, как описано в http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#lookup
@Inject
Instance<Type> instance;
// In the code
try {
instance.get();
}catch (Exception e){
}
Или даже все экземпляры типа
@Inject
Instance<List<Type>> instances
Также метод get() ленив, если вам нужно. Инъекция по умолчанию оценивается во время запуска и генерирует исключение, если не найдено beans, которое может быть введено, bean будет введено во время выполнения, но приложение не запустится, если это невозможно. В документации вы найдете больше примеров, включая фильтрацию инъецируемых экземпляров и многое другое.
Инъекционная инъекция часто пропускается. Это добавляет большую гибкость. Проверьте доступность зависимости до ее получения. Неудовлетворенный get будет генерировать исключение, которое дорого. Использование:
@Inject
Instance<SomeType> instance;
SomeType instantiation;
if (!instance.isUnsatisfied()) {
instantiation = instance.get();
}
Вы можете ограничить кандидатов на инъекции как обычно:
@Inject
@SomeAnnotation
Instance<SomeType> instance;