广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Spring中@Autowired@Resource@Inject三个注解有什么区别
  • 275
分享到

Spring中@Autowired@Resource@Inject三个注解有什么区别

Spring@Autowired注解Spring@Resource注解Spring@Inject注解 2023-03-06 11:03:28 275人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录@Autowired@Inject@Resourcejavax.annotation.Resource jdk 内置的,jsR-250 中的注解。 依赖注入通过 org.spri

javax.annotation.Resource

jdk 内置的,jsR-250 中的注解。

依赖注入通过 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor 来处理。

org.springframework.beans.factory.annotation.Autowired
org.springframework.beans.factory.annotation.Value
javax.inject.Inject

JSR-330 中的注解,作用同 @Autowired

依赖注入通过 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 来处理。

org.springframework.beans.factory.annotation.Qualifier
javax.inject.Qualifier

依赖注入通过 org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver 来处理。

@Autowired

spring 自带的注解。

注入顺序

按照 type 在 上下文中查找匹配的 bean

如果有多个 bean,按照 name 进行匹配

  • 如果有 @Qualifier 注解,按照 @Qualifier 指定的 name 进行匹配
  • 如果没有,按照变量名进行匹配

匹配不到,报错。因为 required 默认为 true,不想注入设置此 bean @Autowired(required=false)。

@Inject

在 spring 中,@Inject 和 @Autowired 相同。

@Inject 和 @Autowired 区别

@Inject 是 javaee 6 及以上版本包里的。

@Autowired 可以设置 required=false 而 @Inject 没有这个属性。

@Resource

有两个重要的属性,name 和 type,spring 将 name 属性解析为 bean 的名字,type 解析为 bean 的类型。如果未指定 name,取变量名给 name 赋值。

CommonAnnotationBeanPostProcessor 中Resource 赋值源码


    private class ResourceElement extends LookupElement {
        private final boolean lazyLookup;
        public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
            super(member, pd);
            Resource resource = ae.getAnnotation(Resource.class);
            String resourceName = resource.name();
            Class<?> resourceType = resource.type();
            this.isDefaultName = !StringUtils.hasLength(resourceName);
            if (this.isDefaultName) {
                resourceName = this.member.getName();
                if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
                    resourceName = Introspector.decapitalize(resourceName.substring(3));
                }
            }
            else if (embeddedValueResolver != null) {
                resourceName = embeddedValueResolver.resolveStringValue(resourceName);
            }
            if (Object.class != resourceType) {
                checkResourceType(resourceType);
            }
            else {
                // No resource type specified... check field/method.
                resourceType = getResourceType();
            }
            this.name = (resourceName != null ? resourceName : "");
            this.lookupType = resourceType;
            String lookupValue = resource.lookup();
            this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
            Lazy lazy = ae.getAnnotation(Lazy.class);
            this.lazyLookup = (lazy != null && lazy.value());
        }
        @Override
        protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
            return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
                    getResource(this, requestingBeanName));
        }
    }

在变量名相同的情况下报错

The bean could not be injected as a because it is a JDK dynamic proxy that implements:

指定了不同type无法解决问题,跟进源码发现是 Spring Boot 把异常给处理了

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'productInit': 
Injection of resource dependencies failed; 
nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: 
Bean named 'example2ProductMapper' is expected to be of type 'com.alibaba.cloud.youxia.manager.ProductManager' but was actually of type 'com.sun.proxy.$Proxy47'

想到在 DefaultListableBeanFactory 中 beanDefinitionMap 按照名称和 BeanDefinition 键值对的问题,名称和注入的对象一一对应,不然就会出现不对应的问题

注入规则

  • 如果未指定 name,取变量名从上下文中查找名称匹配的 bean 进行注入,找不到或者注入的变量名与类型无法对应抛出异常。
  • 如果指定了 name,则从上下文中查找名称匹配的 bean 进行注入,找不到抛出异常。
  • 如果指定了 type,有两种情况

通过变量名从上下文中查找不到对应的 bean,则通过 type则从上下文中查找类型匹配的 bean 进行注入,找不到抛出异常。

通过变量名从上下文中找到对应的 bean但是注入的类型与无法与DefaultListableBeanFactory 中 beanDefinitionMap中通过变量名得到的 BeanDefinition 类型一致,抛出异常。

  • 既没有指定 name,又没有指定 type,默认按照变量名进行注入。
  • 如果同时指定了 name 和 type,从上下文中找到唯一匹配的 bean 进行注入,找不到抛出异常。

匹配顺序为

变量名 → 指定的 name → 指定的 type

如果注入的 bean 变量名相同,但是类型不同,通过 name 指定是修改代码量最小的办法。

到此这篇关于Spring中@Autowired @Resource @Inject三个注解有什么区别的文章就介绍到这了,更多相关Spring @Autowired @Resource @Inject内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Spring中@Autowired@Resource@Inject三个注解有什么区别

本文链接: https://www.lsjlt.com/news/198598.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作