spring使用注解注入报错-util报错 'util:map'.

在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
我想让Spring给controller注入一个Map&String, Object&,我应该怎么配置?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
谢谢邀请回答。使用工厂bean可以实现,参考代码如下:
1:创建map的工厂bean
package com.blog.
import java.util.HashM
import java.util.M
import org.springframework.beans.factory.FactoryB
* @author zl
public class ConfigMapFactory implements FactoryBean&Map&String,Object&& {
public Map&String,Object& getObject() throws Exception {
Map&String,Object& configMap = new HashMap&String,Object&();
configMap.put("hello", "world");
return configM
public Class&?& getObjectType() {
return Map.
public boolean isSingleton() {
2:spring的配置文件中配置:
&bean id="configMap" class="com.blog.factory.ConfigMapFactory"&&/bean&
3:controller层注入
@Controller
public class BlogController extends BaseController{
@Autowired
private CommentService commentS
@Autowired
private BlogService blogS
@Resource(name="configMap")//这边需要使用Resource注解
private Map&String,Object& configM
@RequestMapping("/")
public String index(Model model){
System.out.println(configMap.get("hello"));//打印出world
return "index";
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你配置个Java Bean哈 在吧Bean注入哈
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
依赖注入不是配置文件配置的嘛?
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。博客分类:
一般我们知道在property属性里面定义一个无id的map是比较容易的, 但是如何将map定义一个单独的bean, 以便重用, google了一下, 给出了说明, 不过有些问题, 没有value那个节点, 不知道是否spring版本的问题, 修改之后, 备注一下.
&bean id="SymbolMap" class="java.util.HashMap"&
&constructor-arg&
&key&&value&&![CDATA[djia]]&&/value&&/key&
&value&&![CDATA[us&dji]]&&/value&
&/constructor-arg&
还用另外一种形式:
&bean id="emails" class="org.springframework.beans.factory.config.MapFactoryBean"&
&property name="sourceMap"&
&entry key="pechorin" value="pechorin@hero.org"/&
&entry key="raskolnikov" value="raskolnikov@slums.org"/&
&entry key="stavrogin" value="stavrogin@gov.org"/&
&entry key="porfiry" value="porfiry@gov.org"/&
&/property&
&bean id="fieldMap" class="org.springframework.beans.factory.config.MapFactoryBean"&
&property name="sourceMap"&
&entry key="title" value-ref="obj"&&/entry&
&entry key="reserve_price" value-ref="double"&&/entry&
&entry key="auction_status" value-ref="obj"&&/entry&
&entry key="quantity" value-ref="obj"&&/entry&
&entry key="options" value-ref="obj"&&/entry&
&entry key="spu_id" value-ref="obj"&&/entry&
&entry key="sold_quantity" value-ref="obj"&&/entry&
&entry key="features" value-ref="obj"&&/entry&
&entry key="category" value-ref="obj"&&/entry&
&entry key="user_id" value-ref="obj"&&/entry&
&entry key="auction_id" value-ref="obj"&&/entry&
&entry key="gmt_modified" value-ref="date"&&/entry&
&entry key="pict_url" value-ref="obj"&&/entry&
&entry key="sync_version" value-ref="obj"&&/entry&
&/property&
&bean id="date" class="java.lang.Class" factory-method="forName"&
&constructor-arg value="java.util.Date"/&
&bean id="double" class="java.lang.Class" factory-method="forName"&
&constructor-arg value="java.lang.Double"/&
&bean id="obj" class="java.lang.Class" factory-method="forName"&
&constructor-arg value="java.lang.Object"/&
浏览 39623
浏览: 2109025 次
来自: 杭州
https://github.com/ebottabi/sto ...
能抗能打 写道哥们儿,你好!能共享下那个storm与sprin ...
兄弟,你之前是不是在深圳的正阳公司呆过啊?
先点个赞,写的非常好!有个问题请教下,如果我再bolt里不用e ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'详解Java Spring各种依赖注入注解的区别
转载 &更新时间:日 16:20:08 & 作者:徐刘根
这篇文章主要介绍了详解Java Spring各种依赖注入注解的区别的相关资料,需要的朋友可以参考下
注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired、Resource、Qualifier、Service、Controller、Repository、Component。
Autowired是自动注入,自动从spring的上下文找到合适的bean来注入
Resource用来指定名称注入
Qualifier和Autowired配合使用,指定bean的名称
Service,Controller,Repository分别标记类是Service层类,Controller层类,数据存储层的类,spring扫描注解配置时,会标记这些类要生成bean。
Component是一种泛指,标记类是组件,spring扫描注解配置时,会标记这些类要生成bean。
Spring对于Bean的依赖注入,支持多种注解方式:
javax.annotation
JSR250 (Common Annotations for Java)
javax.inject
JSR330 (Dependency Injection for Java)
@Autowired
org.springframework.bean.factory
直观上看起来,@Autowired是Spring提供的注解,其他几个都是JDK本身内建的注解,Spring对这些注解也进行了支持。但是使用起来这三者到底有什么区别呢?笔者经过方法的测试,发现一些有意思的特性。
区别总结如下:
一、@Autowired有个required属性,可以配置为false,这种情况下如果没有找到对应的bean是不会抛异常的。@Inject和@Resource没有提供对应的配置,所以必须找到否则会抛异常。
二、 @Autowired和@Inject基本是一样的,因为两者都是使用AutowiredAnnotationBeanPostProcessor来处理 依赖注入。但是@Resource是个例外,它使用的是CommonAnnotationBeanPostProcessor来处理依赖注入。当然,两者 都是BeanPostProcessor。
@Autowired和@Inject
- 默认 autowired by type
- 可以 通过@Qualifier 显式指定 autowired by qualifier name。
- 如果 autowired by type 失败(找不到或者找到多个实现),则退化为autowired by field name
- 默认 autowired by field name
- 如果 autowired by field name失败,会退化为 autowired by type
- 可以 通过@Qualifier 显式指定 autowired by qualifier name
- 如果 autowired by qualifier name失败,会退化为 autowired by field name。但是这时候如果 autowired by field name失败,就不会再退化为autowired by type了。
TIPS Qualified name VS Bean name
在Spring设计中,Qualified name并不等同于Bean name,后者必须是唯一的,但是前者类似于tag或者group的作用,对特定的bean进行分类。可以达到getByTag(group)的效果。对 于XML配置的bean,可以通过id属性指定bean name(如果没有指定,默认使用类名首字母小写),通过标签指定qualifier name:
&bean id="lamborghini" class="me.arganzheng.study.spring.autowired.Lamborghini"&
&qualifier value="luxury"/&
&!-- inject any dependencies required by this bean --&
如果是通过注解方式,那么可以通过@Qualifier注解指定qualifier name,通过@Named或者@Component(@Service,@Repository等)的value值指定bean name:
@Component("lamborghini")
@Qualifier("luxury")
public class Lamborghini implements Car {
@Component
@Named("lamborghini")
@Qualifier("luxury")
public class Lamborghini implements Car {
同样,如果没有指定bean name,那么Spring会默认是用类名首字母小写(Lamborghini=&lamborghini)。
三、 通过Anotation注入依赖的方式在XML注入方式之前进行。如果对同一个bean的依赖同时使用了两种注入方式,那么XML的优先。但是不同担心通过Anotation注入的依赖没法注入XML中配置的bean,依赖注入是在bean的注册之后进行的。
四、目前的autowired by type方式(笔者用的是3.2.3.RELEASE版本),Spring的AutowiredAnnotationBeanPostProcessor 实现都是有”bug”的,也就是说@Autowired和@Inject都是有坑的(称之为坑,不称之为bug是因为貌似是故意的。。)。这是来源于线上 的一个bug,也是这边文章的写作原因。现场如下:
application-context.xml中有如下定义:
&xml version="1.0" encoding="UTF-8"?&
&beans xmlns="http://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/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"&
&context:annotation-config /&
&context:component-scan base-package="me.arganzheng.study" /&
&util:constant id="en"
static-field="me.arganzheng.study.spring.autowired.Constants.Language.EN" /&
&util:constant id="ja"
static-field="me.arganzheng.study.spring.autowired.Constants.Language.JP" /&
&util:constant id="ind"
static-field="me.arganzheng.study.spring.autowired.Constants.Language.IND" /&
&util:constant id="pt"
static-field="me.arganzheng.study.spring.autowired.Constants.Language.PT" /&
&util:constant id="th"
static-field="me.arganzheng.study.spring.autowired.Constants.Language.TH" /&
&util:constant id="ar"
static-field="me.arganzheng.study.spring.autowired.Constants.Language.AR" /&
&util:constant id="en-rIn"
static-field="me.arganzheng.study.spring.autowired.Constants.Language.EN_RIN" /&
&util:map id="languageChangesMap" key-type="java.lang.String"
value-type="java.lang.String"&
&entry key="pt" value="pt" /&
&entry key="br" value="pt" /&
&entry key="jp" value="ja" /&
&entry key="ja" value="ja" /&
&entry key="ind" value="ind" /&
&entry key="id" value="ind" /&
&entry key="en-rin" value="en-rIn" /&
&entry key="in" value="en-rIn" /&
&entry key="en" value="en" /&
&entry key="gb" value="en" /&
&entry key="th" value="th" /&
&entry key="ar" value="ar" /&
&entry key="eg" value="ar" /&
&/util:map&
其中static-field应用的常量定义在如下类中:
package me.arganzheng.study.spring.
public interface Constants {
public interface Language {
public static final String EN = "CommonConstants.LANG_ENGLISH";
public static final String JP = "CommonConstants.LANG_JAPANESE";
public static final String IND = "CommonConstants.LANG_INDONESIAN";
public static final String PT = "CommonConstants.LANG_PORTUGUESE";
public static final String TH = "CommonConstants.LANG_THAI";
public static final String EN_RIN = "CommonConstants.LANG_ENGLISH_INDIA";
public static final String AR = "CommonConstants.LANG_Arabic";
然后如果我们在代码中如下声明依赖:
public class AutowiredTest extends BaseSpringTestCase {
@Autowired
private Map&String, String& languageChangesM
public void testAutowired() {
notNull(languageChangesMap);
System.out.println(languageChangesMap.getClass().getSimpleName());
System.out.println(languageChangesMap);
Guess what,诡异的事情发生了!
运行结果如下:
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
严重: Caught exception while allowing TestExecutionListener
[org.springframework.test.context.support.DependencyInjectionTestExecutionListener@5c51ee0a] to prepare test instance [me.arganzheng.study.spring.autowired.AutowiredTest@6e301e0]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'me.arganzheng.study.spring.autowired.AutowiredTest': Injection of autowired nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.Map me.arganzheng.study.spring.autowired.AutowiredTest.languageChangesM nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
ed by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:843)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
... 28 more
debug了一下,发现确实是Spring的一个bug。在DefaultListableBeanFactory的这个方法出问题了:
protected Object doResolveDependency(DependencyDescriptor descriptor, Class&?& type, String beanName,
Set&String& autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
Class&?& keyType = descriptor.getMapKeyType();
if (keyType == null || !String.class.isAssignableFrom(keyType)) {
if (descriptor.isRequired()) {
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
"] must be assignable to [java.lang.String]");
Class&?& valueType = descriptor.getMapValueType();
if (valueType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
Map&String, Object& matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
return matchingB
关键在这一句:Map
严重: Caught exception while allowing TestExecutionListener
[org.springframework.test.context.support.DependencyInjectionTestExecutionListener@9476189] to prepare test instance [me.arganzheng.study.spring.autowired.AutowiredTest@2d546e21]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=languageChangesMap)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:843)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
... 28 more
debug了一下,发现跟没有指定qualifie name是一样的执行路径。不是指定了bean name了吗?为什么还是autowired by type呢?仔细查看了一下才发现。DefaultListableBeanFactory的doResolveDependency方法对首先对类型做 了区别:
protected Object doResolveDependency(DependencyDescriptor descriptor, Class&?& type, String beanName,
Set&String& autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
if (type.isArray()) {
Class&?& componentType = type.getComponentType();
Map&String, Object& matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return converter.convertIfNecessary(matchingBeans.values(), type);
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class&?& elementType = descriptor.getCollectionType();
if (elementType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
Map&String, Object& matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return converter.convertIfNecessary(matchingBeans.values(), type);
else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
Class&?& keyType = descriptor.getMapKeyType();
if (keyType == null || !String.class.isAssignableFrom(keyType)) {
if (descriptor.isRequired()) {
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
"] must be assignable to [java.lang.String]");
Class&?& valueType = descriptor.getMapValueType();
if (valueType == null) {
if (descriptor.isRequired()) {
throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
Map&String, Object& matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
return matchingB
Map&String, Object& matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (descriptor.isRequired()) {
raiseNoSuchBeanDefinitionException(type, "", descriptor);
if (matchingBeans.size() & 1) {
String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
if (primaryBeanName == null) {
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
if (autowiredBeanNames != null) {
autowiredBeanNames.add(primaryBeanName);
return matchingBeans.get(primaryBeanName);
// We have exactly one match.
Map.Entry&String, Object& entry = matchingBeans.entrySet().iterator().next();
if (autowiredBeanNames != null) {
autowiredBeanNames.add(entry.getKey());
return entry.getValue();
如果是Array,Collection或者Map,则根据集合类中元素的类型来进行autowired by type(Map使用value的类型)。为什么这么特殊处理呢?原来,Spring是为了达到这样的目的:让你可以一次注入所有符合类型的实现,也就是 说可以这样子注入:
@Autowired
private List&Car&
如果你的car有多个实现,那么都会注入进来,不会再报
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [me.arganzheng.study.spring.autowired.Car] is defined:
expected single matching bean but found 2: [audi, toyota].
然而,上面的情况如果你用@Resource则不会有这个问题:
public class AutowiredTest extends BaseSpringTestCase {
@Qualifier("languageChangesMap")
private Map&String, String& languageChangesM
public void testAutowired() {
assertNotNull(languageChangesMap);
System.out.println(languageChangesMap.getClass().getSimpleName());
System.out.println(languageChangesMap);
正常运行:
LinkedHashMap
{pt=pt, br=pt, jp=ja, ja=ja, ind=ind, id=ind, en-rin=en-rIn, in=en-rIn, en=en, gb=en, th=th, ar=ar, eg=ar}
当然,你如果不指定@Qualifier(“languageChangesMap”),同时field name不是languageChangesMap,那么还是一样报错的。
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.annotation.Resource(shareable=true, mappedName=, description=, name=, type=class java.lang.Object, authenticationType=CONTAINER, lookup=)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:843)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:438)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)
... 26 more
而且,@Resource也可以实现上面的List接收所有实现:
public class AutowiredTest extends BaseSpringTestCase {
@Qualifier("languageChangesMap")
private Map&String, String& languageChangesM
private List&Car&
public void testAutowired() {
assertNotNull(languageChangesMap);
System.out.println(languageChangesMap.getClass().getSimpleName());
System.out.println(languageChangesMap);
assertNotNull(cars);
System.out.println(cars.getClass().getSimpleName());
System.out.println(cars);
运行的妥妥的:
LinkedHashMap
{pt=pt, br=pt, jp=ja, ja=ja, ind=ind, id=ind, en-rin=en-rIn, in=en-rIn, en=en, gb=en, th=th, ar=ar, eg=ar}
[me.arganzheng.study.spring.autowired.Audi@579584da, me.arganzheng.study.spring.autowired.Toyota@]
这是因为@Resource注解使用的是CommonAnnotationBeanPostProcessor处理器,跟 AutowiredAnnotationBeanPostProcessor不是同一个作者[/偷笑]。这里就不分析了,感兴趣的同学可以自己看代码研究 一下。
最终结论如下:
1、@Autowired和@Inject
autowired by type 可以 通过@Qualifier 显式指定 autowired by qualifier name(非集合类。注意:不是autowired by bean name!)
如果 autowired by type 失败(找不到或者找到多个实现),则退化为autowired by field name(非集合类)
2、@Resource
默认 autowired by field name
如果 autowired by field name失败,会退化为 autowired by type
可以 通过@Qualifier 显式指定 autowired by qualifier name
如果 autowired by qualifier name失败,会退化为 autowired by field name。但是这时候如果 autowired by field name失败,就不会再退化为autowired by type了
测试工程保存在GitHub上,是标准的maven工程,感兴趣的同学可以clone到本地运行测试一下。
有同事指出Spring官方文档上有这么一句话跟我的结有点冲突:
However, although you can use this convention to refer to specific beans by name, @Autowired is fundamentally about type-driven injection with optional semantic qualifiers. This means that qualifier values, even with the bean name fallback, always have narrowing semantics within the they do not semantically express a reference to a unique bean id.
也就是说@Autowired即使加了@Qualifier注解,其实也是autowired by type。@Qualifier只是一个限定词,过滤条件而已。重新跟进了一下代码,发现确实是这样子的。Spring设计的这个 @Qualifier name 并不等同于 bean name。他有点类似于一个tag。不过如果这个tag是唯一的化,那么其实效果上等同于bean name。实现上,Spring是先getByType,得到list candicates,然后再根据qualifier name进行过滤。
再定义一个兰博基尼,这里使用@Qualifier指定:
package me.arganzheng.study.spring.
import org.springframework.beans.factory.annotation.Q
import org.springframework.stereotype.C
@Component
@Qualifier("luxury")
public class Lamborghini implements Car {
再定义一个劳斯莱斯,这里故意用@Named指定:
package me.arganzheng.study.spring.
import javax.inject.N
import org.springframework.stereotype.C
@Component
@Named("luxury")
public class RollsRoyce implements Car {
测试一下注入定义的豪华车:
package me.arganzheng.study.spring.
import static junit.framework.Assert.assertNotN
import java.util.L
import me.arganzheng.study.BaseSpringTestC
import org.junit.T
import org.springframework.beans.factory.annotation.A
import org.springframework.beans.factory.annotation.Q
* @author zhengzhibin
public class AutowiredTest extends BaseSpringTestCase {
@Autowired
@Qualifier("luxury")
private List&Car& luxuryC
public void testAutowired() {
assertNotNull(luxuryCars);
System.out.println(luxuryCars.getClass().getSimpleName());
System.out.println(luxuryCars);
运行结果如下:
[me.arganzheng.study.spring.autowired.Lamborghini@66b875e1, me.arganzheng.study.spring.autowired.RollsRoyce@58433b76]
补充:Autowiring modes
Spring支持四种autowire模式,当使用XML配置方式时,你可以通过autowire属性指定。
no. (Default) No autowiring. Bean references must be defined via a ref element. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system.
byName. Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name, and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master, and uses it to set the property.
byType. Allows a property to be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, the property is not set.
constructor. Analogous to byType, but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised.
如果使用@Autowired、@Inject或者@Resource注解的时候,则稍微复杂一些,会有一个失败退化过程,并且引入了Qualifier。不过基本原理是一样。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 csrutil 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信