可以在JSR 330中使@Inject成为可选项(如@Autowire(required = false)吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可以在JSR 330中使@Inject成为可选项(如@Autowire(required = false)吗?相关的知识,希望对你有一定的参考价值。

Spring的@Autowire可以配置为如果找不到匹配的autowire候选者,Spring将不会抛出错误:@Autowire(required=false)

是否有等效的JSR-330注释?如果没有匹配的候选人,@Inject总是会失败。有没有办法我可以使用@Inject但没有框架失败,如果没有找到匹配的类型?我无法在那个程度上找到任何文档。

答案

不......在JSR 330中没有可选的等价物...如果你想使用可选注入那么你将不得不坚持使用框架特定的@Autowired注释

另一答案

你可以使用java.util.Optional。如果您使用的是Java 8,而您的Spring版本是4.1或更高版本(请参阅here),而不是

@Autowired(required = false)
private SomeBean someBean;

您可以使用Java 8附带的java.util.Optional类。使用它像:

@Inject
private Optional<SomeBean> someBean;

这个实例永远不会是null,你可以使用它:

if (someBean.isPresent()) {
   // do your thing
}

这样你也可以做构造函数注入,需要一些bean和一些bean可选,提供了很大的灵活性。

注意:不幸的是,Spring不支持Guava的com.google.common.base.Optional(请参阅here),因此只有在使用Java 8(或更高版本)时此方法才有效。

另一答案

实例注入经常被忽视。它增加了很大的灵活性在获取依赖项之前检查依赖项的可用性。不满意的获得将抛出一个昂贵的例外。使用:

@Inject
Instance<SomeType> instance;
SomeType instantiation;

if (!instance.isUnsatisfied()) {
    instantiation = instance.get();
}

您可以正常限制注射候选者:

@Inject
@SomeAnnotation
Instance<SomeType> instance;
另一答案

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;
        }
    }

简而言之,不,不是默认。

默认情况下要查找的方法名称为'required',这不是@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()方法也是惰性求值。默认注入在启动时评估,如果没有找到可以注入的bean则抛出异常,当然会在运行时注入bean,但如果不可能,应用程序将无法启动。在文档中,您将找到更多示例,包括如何过滤注入的实例等等。

以上是关于可以在JSR 330中使@Inject成为可选项(如@Autowire(required = false)吗?的主要内容,如果未能解决你的问题,请参考以下文章

spring 3.1中对JSR-330的支持

JSR-330 JAVA 依赖注入标准API说明

21自动装配-@Resource&@Inject

@Inject和@Autowired以及@Resource区别

Spring下的@Inject@Autowired@Resource注解区别(转)

为啥以及何时在 Spring 中使用 @Inject 而不是 @Autowired? [复制]