最近学习Spring框架:在我自己写代码的过程中,发现,如果@Autowired注解用在属性上的话,最好要将该属性setter的方法去掉,起初的原因是我想测试一下当有两个Bean的类型(Type)一致是,需要让@Autowired配合使用@Qualifier才能找到唯一的bean。首先看一下我的xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?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:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd" > <bean id ="cat222" class ="com.luo.pojo.Cat" > <property name ="catName" value ="hao" /> </bean > <bean id ="dog111" class ="com.luo.pojo.Dog" > <property name ="dogName" value ="yue1" /> </bean > <bean id ="dog" class ="com.luo.pojo.Dog" > <property name ="dogName" value ="yue" /> </bean > <bean id ="people" class ="com.luo.pojo.People" autowire ="byType" > <property name ="name" value ="luo" /> </bean > <context:annotation-config /> </beans >
然后我利用@Autowired 配合 @Qualifier 对dog进行自动装配:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package com.luo.pojo;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;public class People { public String name; @Autowired private Cat cat; @Autowired @Qualifier("dog111") private Dog dog; public String getName () { return name; } public void setName (String name) { this .name = name; } public Cat getCat () { return cat; } public void setCat (Cat cat) { this .cat = cat; } public Dog getDog () { return dog; } public void setDog (Dog dog) { this .dog = dog; } @Override public String toString () { return "People{" + "name='" + name + '\'' + ", cat=" + cat.toString() + ", dog=" + dog.toString() + '}' ; } }
然后我测试了一下可以不可以实现自动装配,结果报错了:
Unsatisfied dependency expressed through bean property ‘dog’: No qualifying bean of type [com.luo.pojo.Dog] is defined: expected single matching bean but found 2: dog111,dog;
报错信息大概就是说无法找到唯一匹配的bean,找到了两个匹配的bean, 分别dog111和dog,诶奇了怪了我不是用@Qualifier(“dog111”)指明了当有多个类型匹配时,取id=“dog111"的那一个bean吗?怎么还会有冲突?
Debug无果后,想到@Autowired有两种使用方式,一种是直接使用在属性上 ,一种是使用在set方法上 ,于是将@Autowired和@Qualifier(“dog111”)使用在set方法上后,成功解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package com.luo.pojo;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;@Component("dok111") public class People { public String name; @Autowired private Cat cat; private Dog dog; public String getName () { return name; } public void setName (String name) { this .name = name; } public Cat getCat () { return cat; } public void setCat (Cat cat) { this .cat = cat; } public Dog getDog () { return dog; } @Autowired @Qualifier("dog111") public void setDog (Dog dog) { this .dog = dog; } @Override public String toString () { return "People{" + "name='" + name + '\'' + ", cat=" + cat.toString() + ", dog=" + dog.toString() + '}' ; } }
为什么会这样呢?在网上搜集了一下信息
当注解写在成员变量(属性)上 就是spring通过读取xml配置返回一个bean
当注解写在set方法上,就是spring通过读取xml配置返回一个bean,然后再用这个bean里面的属性,注入到成员变量当中。
那如果我同时写在属性和set方法上,会通过哪种方式呢?于是我进行了一下测试,将属性和set方法前都写上@Autowired和@Qualifier(“dog111”),代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.luo.pojo;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;@Component("dok111") public class People { public String name; @Autowired private Cat cat; @Autowired @Qualifier("dog111") private Dog dog; public String getName () { return name; } public void setName (String name) { this .name = name; } public Cat getCat () { return cat; } public void setCat (Cat cat) { this .cat = cat; } public Dog getDog () { return dog; } @Autowired @Qualifier("dog111") public void setDog (Dog dog) { System.out.println("调用了set方法" ); this .dog = dog; } @Override public String toString () { return "People{" + "name='" + name + '\'' + ", cat=" + cat.toString() + ", dog=" + dog.toString() + '}' ; } }
最后屏幕输出了调用了set方法 ,好像说明了当同时存在的时候,还是默认使用了set方法 ,先获取bean,再进行配置,这也解释了为什么我们最刚开始只在属性上写@Autowired和@Qualifier(“dog111”)会报错了,因为此时spring还是会通过set方法进行注入,而此时set方法发现两个类型相同,无法唯一匹配就报错了 。
所以解决的方式有两个:
删除掉set方法,使用加在属性上的注解属性直接配置
给set方法前也加上注解