Java Spring各种依赖注入注解的区别.docx
- 文档编号:27855262
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:21
- 大小:23.12KB
Java Spring各种依赖注入注解的区别.docx
《Java Spring各种依赖注入注解的区别.docx》由会员分享,可在线阅读,更多相关《Java Spring各种依赖注入注解的区别.docx(21页珍藏版)》请在冰豆网上搜索。
JavaSpring各种依赖注入注解的区别
pring对于Bean的依赖注入,支持多种注解方式:
@Resource
javax.annotation
JSR250(CommonAnnotationsforJava)
@Inject
javax.inject
JSR330(DependencyInjectionforJava)
@Autowired
org.springframework.bean.factory
Spring
直观上看起来,@Autowired是Spring提供的注解,其他几个都是JDK本身内建的注解,Spring对这些注解也进行了支持。
但是使用起来这三者到底有什么区别呢?
笔者经过方法的测试,发现一些有意思的特性。
区别总结如下:
一、@Autowired有个required属性,可以配置为false,这种情况下如果没有找到对应的bean是不会抛异常的。
@Inject和@Resource没有提供对应的配置,所以必须找到否则会抛异常。
二、@Autowired和@Inject基本是一样的,因为两者都是使用AutowiredAnnotationBeanPostProcessor来处理依赖注入。
但是@Resource是个例外,它使用的是CommonAnnotationBeanPostProcessor来处理依赖注入。
当然,两者都是BeanPostProcessor。
@Autowired和@Inject
-默认autowiredbytype
-可以通过@Qualifier显式指定autowiredbyqualifiername。
-如果autowiredbytype失败(找不到或者找到多个实现),则退化为autowiredbyfieldname
@Resource
-默认autowiredbyfieldname
-如果autowiredbyfieldname失败,会退化为autowiredbytype
-可以通过@Qualifier显式指定autowiredbyqualifiername
-如果autowiredbyqualifiername失败,会退化为autowiredbyfieldname。
但是这时候如果autowiredbyfieldname失败,就不会再退化为autowiredbytype了。
TIPSQualifiednameVSBeanname
在Spring设计中,Qualifiedname并不等同于Beanname,后者必须是唯一的,但是前者类似于tag或者group的作用,对特定的bean进行分类。
可以达到getByTag(group)的效果。
对于XML配置的bean,可以通过id属性指定beanname(如果没有指定,默认使用类名首字母小写),通过标签指定qualifiername:
--injectanydependenciesrequiredbythisbean-->
如果是通过注解方式,那么可以通过@Qualifier注解指定qualifiername,通过@Named或者@Component(@Service,@Repository等)的value值指定beanname:
@Component("lamborghini")
@Qualifier("luxury")
publicclassLamborghiniimplementsCar{
}
或者
@Component
@Named("lamborghini")
@Qualifier("luxury")
publicclassLamborghiniimplementsCar{
}
同样,如果没有指定beanname,那么Spring会默认是用类名首字母小写(Lamborghini=>lamborghini)。
三、通过Anotation注入依赖的方式在XML注入方式之前进行。
如果对同一个bean的依赖同时使用了两种注入方式,那么XML的优先。
但是不同担心通过Anotation注入的依赖没法注入XML中配置的bean,依赖注入是在bean的注册之后进行的。
四、目前的autowiredbytype方式(笔者用的是3.2.3.RELEASE版本),Spring的AutowiredAnnotationBeanPostProcessor实现都是有”bug”的,也就是说@Autowired和@Inject都是有坑的(称之为坑,不称之为bug是因为貌似是故意的。
。
)。
这是来源于线上的一个bug,也是这边文章的写作原因。
现场如下:
application-context.xml中有如下定义:
xmlversion="1.0"encoding="UTF-8"?
>
//www.springframework.org/schema/beans" xmlns: xsi="http: //www.w3.org/2001/XMLSchema-instance"xmlns: aop="http: //www.springframework.org/schema/aop" xmlns: context="http: //www.springframework.org/schema/context" xmlns: util="http: //www.springframework.org/schema/util" xsi: schemaLocation=" http: //www.springframework.org/schema/beanshttp: //www.springframework.org/schema/beans/spring-beans-3.0.xsd http: //www.springframework.org/schema/aophttp: //www.springframework.org/schema/aop/spring-aop-3.0.xsd http: //www.springframework.org/schema/contexthttp: //www.springframework.org/schema/context/spring-context-3.0.xsd http: //www.springframework.org/schema/utilhttp: //www.springframework.org/schema/util/spring-util-2.5.xsd"> annotation-config/> component-scanbase-package="me.arganzheng.study"/> constantid="en" static-field="me.arganzheng.study.spring.autowired.Constants.Language.EN"/> constantid="ja" static-field="me.arganzheng.study.spring.autowired.Constants.Language.JP"/> constantid="ind" static-field="me.arganzheng.study.spring.autowired.Constants.Language.IND"/> constantid="pt" static-field="me.arganzheng.study.spring.autowired.Constants.Language.PT"/> constantid="th" static-field="me.arganzheng.study.spring.autowired.Constants.Language.TH"/> constantid="ar" static-field="me.arganzheng.study.spring.autowired.Constants.Language.AR"/> constantid="en-rIn" static-field="me.arganzheng.study.spring.autowired.Constants.Language.EN_RIN"/> mapid="languageChangesMap"key-type="java.lang.String" value-type="java.lang.String"> map> 其中static-field应用的常量定义在如下类中: packageme.arganzheng.study.spring.autowired; publicinterfaceConstants{ publicinterfaceLanguage{ publicstaticfinalStringEN="CommonConstants.LANG_ENGLISH"; publicstaticfinalStringJP="CommonConstants.LANG_JAPANESE"; publicstaticfinalStringIND="CommonConstants.LANG_INDONESIAN"; publicstaticfinalStringPT="CommonConstants.LANG_PORTUGUESE"; publicstaticfinalStringTH="CommonConstants.LANG_THAI"; publicstaticfinalStringEN_RIN="CommonConstants.LANG_ENGLISH_INDIA"; publicstaticfinalStringAR="CommonConstants.LANG_Arabic"; } } 然后如果我们在代码中如下声明依赖: publicclassAutowiredTestextendsBaseSpringTestCase{ @Autowired privateMap @Test publicvoidtestAutowired(){ notNull(languageChangesMap); System.out.println(languageChangesMap.getClass().getSimpleName()); System.out.println(languageChangesMap); } } Guesswhat,诡异的事情发生了! 运行结果如下: LinkedHashMap {en=CommonConstants.LANG_ENGLISH,ja=CommonConstants.LANG_JAPANESE,ind=CommonConstants.LANG_INDONESIAN,pt=CommonConstants.LANG_PORTUGUESE,th=CommonConstants.LANG_THAI,ar=CommonConstants.LANG_Arabic,en-rIn=CommonConstants.LANG_ENGLISH_INDIA} 也就是说Map 严重: CaughtexceptionwhileallowingTestExecutionListener[org.springframework.test.context.support.DependencyInjectionTestExecutionListener@5c51ee0a]topreparetestinstance[me.arganzheng.study.spring.autowired.AutowiredTest@6e301e0] org.springframework.beans.factory.BeanCreationException: Errorcreatingbeanwithname'me.arganzheng.study.spring.autowired.AutowiredTest': Injectionofautowireddependenciesfailed;nestedexceptionisorg.springframework.beans.factory.BeanCreationException: Couldnotautowirefield: privatejava.util.Mapme.arganzheng.study.spring.autowired.AutowiredTest.languageChangesMap;nestedexceptionisorg.springframework.beans.factory.NoSuchBeanDefinitionException: Noqualifyingbeanoftype[java.lang.String]foundfordependency[mapwithvaluetypejava.lang.String]: expectedatleast1beanwhichqualifiesasautowirecandidateforthisdependency.Dependencyannotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} ... Causedby: org.springframework.beans.factory.NoSuchBeanDefinitionException: Noqualifyingbeanoftype[java.lang.String]foundfordependency[mapwithvaluetypejava.lang.String]: expectedatleast1beanwhichqualifiesasautowirecandidateforthisdependency.Dependencyannotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} atorg.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java: 986) atorg.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java: 843) atorg.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java: 768) atorg.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java: 486) ...28more debug了一下,发现确实是Spring的一个bug。 在DefaultListableBeanFactory的这个方法出问题了: protectedObjectdoResolveDependency(DependencyDescriptordescriptor,Class >type,StringbeanName, Set ... elseif(Map.class.isAssignableFrom(type)&&type.isInterface()){ Class >keyType=descriptor.getMapKeyType(); if(keyType==null||! String.class.isAssignableFrom(keyType)){ if(descriptor.isRequired()){ thrownewFatalBeanException("Keytype["+keyType+"]ofmap["+type.getName()+ "]mustbeassignableto[java.lang.String]"); } returnnull; } Class >valueType=descriptor.getMapValueType(); if(valueType==null){ if(descriptor.isRequired()){ thrownewFatalBeanException("Novaluetypedeclaredformap["+type.getName()+"]"); } returnnull; } Map if(matchingBeans.isEmpty()){ if(descriptor.isRequired()){ raiseNoSuchBeanDefinitionException(valueType,"mapwithvaluetype"+valueType.getName(),descriptor); } returnnull; } if(autowiredBeanNames! =null){ autowiredBeanNames.addAll(matchingBeans.keySet()); } returnmatchingBeans; } ... } 关键在这一句: Map 严重: CaughtexceptionwhileallowingTestExecutionListener[org.springframework.test.context.support.DependencyInjectionTestExecutionListener@9476189]topreparetestinstance[me.arganzheng.study.spring.autowired.AutowiredTest@2d546e21] ... Causedby: org.springframework.beans.factory.NoSuchBeanDefinitionException: Noqualifyingbeanoftype[java.lang.String]foundfordependency[mapwithvaluetypejava.lang.String]: expectedatleast1beanwhichqualifiesasautowirecandidateforthisdependency.Dependencyannotations: {@org.springframework.beans.factory.annotation.Autowired(required=true),@org.springframework.beans.factory.annotation.Qualifier(value=languageChangesMap)} atorg.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java: 986) atorg.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java: 843) atorg.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java: 768) atorg.springframework.beans.factory
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java Spring各种依赖注入注解的区别 Spring 各种 依赖 注入 注解 区别