定义
@Autowired:默认byType进行自动装配,可以用于构造器、字段、方法注入,且必须有一个Bean候选者注入;如果允许出现0个Bean候选者需要设置属性"required=false"
,"required"
属性含义和@Required一样,只是@Required只适用于基于XML配置的setter注入方式。
@Resource:如果name和type属性都不指定,默认将先byName自动装配,找不到再byType;如果配置name属性,使用byName进行自动装配,而使用type时则使用byType进行装配;如果同时指定name和type,则从容器中找唯一匹配的bean装配,找不到抛出异常。
@Autowired 与@Resource区别:
- @Autowired与@Resource都可以用来装配bean,都可以写在字段或setter方法上。
- @Resource是JDK提供的注解,默认按照名称进行装配,名称可通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是如果name属性一旦指定,就只会按照名称进行装配。
- @Autowired默认按类型装配(Spring提供的注解),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:
@Autowired(required=false);
如果想使用名称装配可以结合@Qualifier注解进行使用,如下:
@Autowired
@Qualifier("baseDao")
private BaseDao baseDao;
@Resource装配顺序:
①如果同时指定name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。
@Resource 注解应该只用于setter方法注入和字段属性注入,不能提供如@Autowired多参数方法注入;
@Resource 首先将从JNDI环境中查找资源,如果没找到默认再到Spring容器中查找,因此如果JNDI环境中有和Spring容器同名的资源时需要注意。
autowired机制
Spring引入Autowire(自动装配)机制就是为了解决<bean>
标签下<property>
标签过多的问题:
如果一个Bean中要注入的对象过多,那将导致Spring配置文件非常冗长,可读性与维护性差,配置麻烦且一不小心就容易出错。
使用Autowire去除<property>
标签
autowire有两处配置点:
可以配置在<beans>
根标签下,表示对全局<bean>
起作用,属性名为default-autowire
可以配置在<bean>
标签下,表示对当前<bean>
起作用,属性名为autowire
通常都是在<beans>
根标签下配置自动装配比较多,default-autowire有四种取值:
- no:默认,即不进行自动装配,每一个对象的注入比如依赖一个
<property>
标签 - byName:按照beanName进行自动装配,使用setter注入
- byType:按照bean类型进行自动装配,使用setter注入
- constructor:不常用,与byType差不多,不过最终属性通过构造函数进行注入
byName意为在spring配置文件中查询beanName与属性名一致的bean并进行装配,若类型不匹配则报错;byType意为在spring配置文件中查询与属性类型一致的bean并进行装配,若有多个相同类型则报错。
byType装配出现多个相同类型的bean及解决方案
byType的装配方式是在Spring配置文件中寻找属性类型与bean类型一致的bean,如果属性类型在Spring配置文件中有多个相同类型的bean时,会报错:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '*' defined in class path resource [*.xml]:
Unsatisfied dependency expressed through bean property '*': : No unique bean of type [*.*.*] is defined: expected single matching bean but
found 2: [*, *]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [*.*.*] is
defined: expected single matching bean but found 2: [*, *]
解决方法:
- 将不需要进行自动装配的bean进行排除,设置其属性
autowire-candidate="false"
; - 当有多个候选者时,优先使用其中哪个候选者,对要作为自动装配候选者的bean设置
primary="true"
;
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'apiController': Unsatisfied dependency expressed through field 'googleSqlService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'googleSqlService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'adplanPutService' is expected to be of type 'com.aaa.cbd.platform.service.AdplanPutGoogleService' but was actually of type 'com.aaa.cbd.platform.service.AdplanPutService'