@Autowiredjava的注解是什么到底是byType还是byName

spring mcv(11)
前面说到了关于在xml中有提供default-autowire的配置信息,从spring 2.5开始,spring又提供了一个Autowired以及javaEE中标准的Resource注释,都好像可以实现类似的自动注入。那么是不是每个都实现同样的方式呢,这里面的几个配置到底有哪些异同点。哪个更全,哪个更优先,这些都需要对spring的内部原理有详细的了解才可以进行了解。
在以下文章时,首先有几个概念需要列出:
字段名称:即fieldName,这个即propertyDescriper的getPropertyName返回信息。
setter名称:即方法setter除set之外的名称,如setAbc,则名称为abc,这里的abc不一定和fieldName相同。
参数名称:即在参数中所定义的参数的名称,如setAbc(Abc a123)。这里的参数名称就是a123。
本文所使用spring版本为spring3.0.2。
处理类和处理顺序异同
default-autowire是在xml中进行配置的,而这个配置从spring初始就提供了。而Autowired注解,则是从2.5自支持以java1.5之后才出现的,这就必然导致对相应的处理以及逻辑是不同的。那么每个方式的处理顺序是怎样的呢,从我写的文章:.也可以由下面的代码得出:
&&&&&&&&if
(mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
&&&&&&&&&&&&&&&&mbd.getResolvedAutowireMode()
== RootBeanDefinition.AUTOWIRE_BY_TYPE) {
&&&&&&&&&&&&MutablePropertyValues
newPvs = new
MutablePropertyValues(pvs);
&&&&&&&&&&&&
&&&&&&&&&&&&if
(mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
&&&&&&&&&&&&&&&&autowireByName(beanName,
mbd, bw, newPvs);
&&&&&&&&&&&&}
&&&&&&&&&&&&
&&&&&&&&&&&&if
(mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
&&&&&&&&&&&&&&&&autowireByType(beanName,
mbd, bw, newPvs);
&&&&&&&&&&&&}
&&&&&&&&&&&&pvs
&&&&&&&&&&&&for
(BeanPostProcessor bp : getBeanPostProcessors()) {
&&&&&&&&&&&&&&&&if
(bp instanceof
InstantiationAwareBeanPostProcessor) {
&&&&&&&&&&&&&&&&&&&&InstantiationAwareBeanPostProcessor
ibp = (InstantiationAwareBeanPostProcessor)
&&&&&&&&&&&&&&&&&&&&pvs
= ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
以上代码来源于类AbstractAutowireCapableBeanFactory的populateBean方法。从上可以看出,spring首先处理在bean定义上的autowire属性,然后再处理后面的InstantiationAwareBeanPostProcessor类。首先bean定义上的autowire属性,可以来自于&bean&定义时autowire属性,也可以来自于整个xml定义中&beans&节点中的default-autowire属性。
那么@Autowired注解和@Resource注解在哪儿处理呢,看上面的代码,有个InstantiationAwareBeanPostProcessor类,如果你仔细查看里面的实现,你可以发现里面即为处理相应注解类的实现。而这些注解类,只要在xml中启用了&context:annotation-config/&,即可以开启这些类了。而我们的Autowired注解,由AutowiredAnnotationBeanPostProcessor来进行处理,而Resource类,则由CommonAnnotationBeanPostProcessor进行处理。
处理内容和处理范围异同
xml中default-autowire配置
首先,针对于xml配置中的default-autowire配置,我们都知道byName是通过name注入而byType是通过类型注入。byType没有好争议的,是根据类型从所有bean查找满足条件的bean,如果找到一个,则使用此bean。但是如果没有找到,则不会报错,但是如果发现有2个以上的侯选者,则会报No unique bean of type的错误信息。
针对于byName,则是根据propertyDescriptor,即满足bean规范的字段信息进行注入。之所以这里重点提bean规范,请看以下代码:
TxInterface tx2;
TxInterface getTx3() {
&&&&return
setTx5(TxInterface tx3) {
&&&&this.tx2
这里是不会进行任何注入的,因为里面的tx2,根本不满足bean规范。但如果将方法setTx5修改为setTx2,则就满足bean规范,就会进行byName注入了。
@Autowired注解
再来看Autowired注解,有的人说autowired注解是按照byType方式进行配置,其实这个说法是错的,至少是不完善的。为什么呢,这需要我们来查看整个autowire的流程,如以下代码示:
Map&String,
Object& matchingBeans = findAutowireCandidates(beanName, type, descriptor);
(matchingBeans.isEmpty()) {
(descriptor.isRequired()) {
&&&&&&&&raiseNoSuchBeanDefinitionException(type,
descriptor);
&&&&return
(matchingBeans.size() & 1)
&&&&String
primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
(primaryBeanName == null)
&&&&&&&&throw
NoSuchBeanDefinitionException(type, &expected
single matching bean but found &
&&&&&&&&&&&&&&&&matchingBeans.size()
+ matchingBeans.keySet());
(autowiredBeanNames != null)
&&&&&&&&autowiredBeanNames.add(primaryBeanName);
&&&&return
matchingBeans.get(primaryBeanName);
Map.Entry&String,
Object& entry = matchingBeans.entrySet().iterator().next();
(autowiredBeanNames != null)
&&&&autowiredBeanNames.add(entry.getKey());
entry.getValue();
以上代码来自于类DefaultListableBeanFactory的doResolveDependency方法。这是由类AutowiredAnnotationBeanPostProcessor类通过调用inject方法时,需要通过调用beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter)来解析引用信息。我们仔细看以上的逻辑,可以从下面的顺序进行处理。
这个逻辑与byType类似,但还不完全相同。不相同的则在第3点处理上,byType如果多于一个,则直接抛出异常。而这里有一个寻找最优bean的过程。即方法determinePrimaryCandidate的实现。实现代码不再列出。但根据@Autowired所放置位置有所不同。
放置在setter方法上,则使用MethodParameter的parameterName进行查找,请注意这里的parameterName。这个属性只有在编译时保留了debug的localVariable才会存在,否则即为null属性。这个属性即参数的名称。如果localVariable不存在,则直接退化为byType。如果有,就按照参数名称进行查找。这里的参数名称不是setter后面的名称,也不是字段名。如以下代码所示:
setTx2(TxInterface tx1) {this.tx2
这里的名称为tx1,而不是tx2。
放置在字段上,则直接使用字段名称。进行查找。
@Resource注解
最后看Resource注解,也有的人说resource是按byName注解,即就完全错了。实际上Resource根本不会走byName方式,我们来看@Resource如何寻找一个bean。默认在不写Resource(name)的情况下:
name = element.
(this.fallbackToDefaultTypeMatch
&& element.isDefaultName &&
&&&&&&&&factory
instanceof
AutowireCapableBeanFactory && !factory.containsBean(name)) {
&&&&autowiredBeanNames
LinkedHashSet&String&();
&&&&resource
= ((AutowireCapableBeanFactory) factory).resolveDependency(
&&&&&&&&&&&&element.getDependencyDescriptor(),
requestingBeanName, autowiredBeanNames, null);
&&&&resource
= factory.getBean(name, element.lookupType);
&&&&autowiredBeanNames
= Collections.singleton(name);
(factory instanceof
ConfigurableBeanFactory) {
&&&&ConfigurableBeanFactory
beanFactory = (ConfigurableBeanFactory)
(String autowiredBeanName : autowiredBeanNames) {
&&&&&&&&beanFactory.registerDependentBean(autowiredBeanName,
requestingBeanName);
以上代码来自于类CommonAnnotationBeanPostProcessor中的autowireResource方法,是由此类通过getResourceToInject获取将要注入的bean来调用的。上面的方法详细描述了整个过程,如下所示:
从上面的第三步,可以看出,Resource在没有根据name查找到的情况下,会走Autowire的方式。所以,从范围来看Resouce的查找范围比Autowire范围更大。
再来看第1步,获取element的名称,这里说是element的名称,因为它的来源有2个地方。一是在resouce注解中配置的name属性,第二就是setter名称或者是field名称(取决于@Resource的配置地点),。这里说的是setter名称,而不是属性名称,这就是需要注意的地方。来源代码如下所示:
resourceName = resource.name();
this.isDefaultName
= !StringUtils.hasLength(resourceName);
(this.isDefaultName)
&&&&resourceName
= this.member.getName();
(this.member
instanceof
Method && resourceName.startsWith(&set&)
&& resourceName.length() & 3)
&&&&&&&&resourceName
= Introspector.decapitalize(resourceName.substring(3));
来源于类ResourceElement的initAnnotation方法。因此,如果方法为如下所示:
setTx2(TxInterface tx5) {
&&&&this.tx4
则获取到的name就是tx2,而不是字段名称tx4。当然,上面的写法不是标准的java bean规范写法,但只是演示这种情况。那么,在系统存在多个满足type的情况下,如果上面的方法中的tx2的bean未找到,那么接下来就寻找名为tx5(autowire规则),再找不到就该报Not Unique异常了。
值得注意的是,如果在使用resource时,根据resource的name找到了bean,但该bean并不是所需要的bean类型,则就要报类型不匹配错误了。即spring在查找时,并没有保证类型判断,即你配置一个name的tx2的bean,但该类型即为TxInterface2而不是TxInterface,则spring在后期直接报异常,而不会fallback了。但Autowired注解则不会产生这种情况,因为它只会从满足type的情况中的bean中查找。
在使用Autowired注解和Resource注解以及xml中的default-autowire注解时,需要详细地了解每个注解的工作方式和工作范围,在大多数情况下。这几种方式都差不多,但在细节方面有差异。从笔者对于代码的严谨角度,我并不推荐在xml中配置default-autowire,因为这会导致所有的bean,不管需不需要注入,spring都会帮你注入。从一方面是好事,从另一方面就管得太多。如果确实要配置default-autowire,请再配置另一个属性default-autowire-candidates,这个属性可以固定default-autowire的范围,比如*Service,可以只针对Service结尾的bean进行autowire包装。
最后,@Autowire注解不是xml配置中的default-autowire-byType,而@Resource也不是@Autowire,更不是xml配置中的default-autowire-byName。不能够简单地混为一谈。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:209488次
积分:3402
积分:3402
排名:第10205名
原创:125篇
转载:75篇
评论:14条
(4)(1)(2)(5)(23)(33)(7)(6)(3)(14)(38)(14)(11)(11)(13)(14)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&6498人阅读
Java Web(14)
首先要知道另一个东西,default-autowire,它是在xml文件中进行配置的,可以设置为byName、byType、constructor和autodetect;比如byName,不用显式的在bean中写出依赖的对象,它会自动的匹配其它bean中id名与本bean的set**相同的,并自动装载。
@Autowired是用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源。
两者的功能是一样的,就是能减少或者消除属性或构造器参数的设置,只是配置地方不一样而已。
autowire四种模式的区别:
先看一下bean实例化和@Autowired装配过程:
一切都是从bean工厂的getBean方法开始的,一旦该方法调用总会返回一个bean实例,无论当前是否存在,不存在就实例化一个并装配,否则直接返回。(Spring MVC是在什么时候开始执行bean的实例化过程的呢?很简单就在组件扫描完成之后)
实例化和装配过程中会多次递归调用getBean方法来解决类之间的依赖。
Spring几乎考虑了所有可能性,所以方法特别复杂但完整有条理。
@Autowired最终是根据类型来查找和装配元素的,但是我们设置了&beans default-autowire="byName"/&后会影响最终的类型匹配查找。因为在前面有根据BeanDefinition的autowire类型设置PropertyValue值得一步,其中会有新实例的创建和注册。就是那个autowireByName方法。
下面通过@Autowired来说明一下用法
Setter 方法中的 @Autowired
你可以在 JavaBean中的 setter 方法中使用 @Autowired 注解。当 Spring遇到一个在 setter 方法中使用的 @Autowired 注解,它会在方法中执行 byType 自动装配。
这里是 TextEditor.java 文件的内容:
package com.
import org.springframework.beans.factory.annotation.A
public class TextEditor {
private SpellChecker spellC
@Autowired
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellC
public SpellChecker getSpellChecker( ) {
return spellC
public void spellCheck() {
spellChecker.checkSpelling();
下面是另一个依赖的类文件 SpellChecker.java 的内容:
package com.
public class SpellChecker {
public SpellChecker(){
System.out.println("Inside SpellChecker constructor." );
public void checkSpelling(){
System.out.println("Inside checkSpelling." );
下面是 MainApp.java 文件的内容:
package com.
import org.springframework.context.ApplicationC
import org.springframework.context.support.ClassPathXmlApplicationC
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
TextEditor te = (TextEditor) context.getBean("textEditor");
te.spellCheck();
下面是配置文件 Beans.xml:
&?xml version="1.0" encoding="UTF-8"?&
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&
id="textEditor" class="com.tutorialspoint.TextEditor"&
id="spellChecker" class="com.tutorialspoint.SpellChecker"&
一旦你已经完成的创建了源文件和 bean 配置文件,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:
Inside SpellChecker constructor.
Inside checkSpelling.
属性中的 @Autowired
你可以在属性中使用 @Autowired 注解来除去 setter 方法。当时使用 为自动连接属性传递的时候,Spring 会将这些传递过来的值或者引用自动分配给那些属性。所以利用在属性中 @Autowired 的用法,你的 TextEditor.java 文件将变成如下所示:
package com.
import org.springframework.beans.factory.annotation.A
public class TextEditor {
@Autowired
private SpellChecker spellC
public TextEditor() {
System.out.println("Inside TextEditor constructor." );
public SpellChecker getSpellChecker( ){
return spellC
public void spellCheck(){
spellChecker.checkSpelling();
下面是配置文件 Beans.xml:
&?xml version="1.0" encoding="UTF-8"?&
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&
id="textEditor" class="com.tutorialspoint.TextEditor"&
id="spellChecker" class="com.tutorialspoint.SpellChecker"&
一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:
Inside TextEditor constructor.
Inside SpellChecker constructor.
Inside checkSpelling.
构造函数中的 @Autowired
你也可以在构造函数中使用 @Autowired。一个构造函数 @Autowired 说明当创建 bean 时,即使在 XML 文件中没有使用 元素配置 bean ,构造函数也会被自动连接。让我们检查一下下面的示例。
这里是 TextEditor.java 文件的内容:
package com.
import org.springframework.beans.factory.annotation.A
public class TextEditor {
private SpellChecker spellC
@Autowired
public TextEditor(SpellChecker spellChecker){
System.out.println("Inside TextEditor constructor." );
this.spellChecker = spellC
public void spellCheck(){
spellChecker.checkSpelling();
下面是配置文件 Beans.xml:
&?xml version="1.0" encoding="UTF-8"?&
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&
id="textEditor" class="com.tutorialspoint.TextEditor"&
id="spellChecker" class="com.tutorialspoint.SpellChecker"&
一旦你在源文件和 bean 配置文件中完成了上面两处改变,让我们运行一下应用程序。如果你的应用程序一切都正常的话,这将会输出以下消息:
Inside TextEditor constructor.
Inside SpellChecker constructor.
Inside checkSpelling.
@Autowired 的(required=false)选项
默认情况下,@Autowired 注解意味着依赖是必须的,它类似于 @Required 注解,然而,你可以使用 @Autowired 的 (required=false) 选项关闭默认行为。
即使你不为 age 属性传递任何参数,下面的示例也会成功运行,但是对于 name 属性则需要一个参数。你可以自己尝试一下这个示例,因为除了只有 Student.java 文件被修改以外,它和 @Required 注解示例是相似的。
package com.
import org.springframework.beans.factory.annotation.A
public class Student {
@Autowired(required=false)
public void setAge(Integer age) {
this.age =
public Integer getAge() {
@Autowired
public void setName(String name) {
this.name =
public String getName() {
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:34514次
排名:千里之外
原创:69篇
(1)(4)(1)(2)(1)(5)(1)(5)(2)(26)(1)(5)(24)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'当前位置: →
→ @autowired与@qualifer的使用区别备忘
@autowired与@qualifer的使用区别备忘
& 作者及来源: highriver - 博客园 &
&收藏到→_→:
摘要: @autowired与@qualifer的使用区别备忘
"@autowired与@qualifer的使用区别备忘"::
使用@autowired注释进行bytype注入,如果需要byname(byname就是通过id去标识)注入,增加@qualifier注释@qualifer如果没有的话, 报的错如下:no unique bean of type [org.springframework.transaction.platformtransactionmanager] is defined: expected single matching bean but found 2: [transactionmanager, jmstransactionmanager]原因:比如配置文件中有二个bean.&bean id="jmstransactionmanager"&&& &&& class="org.springframework.jms.connection.jmstransactionmanager"&&&& &&& &property name="connectionfactory"&&& &&& &&& ref="advancedconnectionfactory" /&&&& &/bean&&bean id="transactionmanager"&&& &&& class="org.springframework.jdbc.datasource.datasourcetransactionmanager"&&&& &&& &property name="datasource"&&&& &&& &&& &ref bean="cpcdatasource" /&&&& &&& &/property&&&& &/bean&表面看起来是不同类型的类,但是由于在*service里面注入的属性类型是platformtransactionmanager.由于上面的二个bean都实现了这个接口.这样@autowired时,由于是bytype注入,就不能识别.此时就需要再加上@qualifer通过id去识别.而如果没有使用@service的话,报错如下:no unique bean of type ..... expected at least 1 matching bean注意,这与上面的提示信息区别.搜索此文相关文章:此文来自: 马开东博客
网址: 站长QQ
@autowired与@qualifer的使用区别备忘_博客园相关文章
博客园_总排行榜
博客园_最新
博客园_月排行榜
博客园_周排行榜
博客园_日排行榜<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&}

我要回帖

更多关于 alias是什么注解 的文章

更多推荐

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

点击添加站长微信