Spring——@Autowire冲突问题
spring中使用@Autowire实现依赖注入。在使用的时候需要注意的是,满足注入条件的bean有多个的时候需要添加标识来区分目前需要注入的是哪个bean。
好,下面上货:
1、新建一个maven项目
mvn archetype:generate -DarchetypeCatalog=internal
2、修改pom文件
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.3.7.RELEASE</springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.xueyou.demo.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
3、先看一下类图:
4、Eat接口
package com.xueyou.demo2;
public interface Eat {
void eatMeal();
}
EatImpl1
package com.xueyou.demo2;
import org.springframework.stereotype.Component;
@Component
public class EatImpl1 implements Eat {
@Override
public void eatMeal() {
System.out.println("this is eatImpl1");
}
}
EatImpl2
package com.xueyou.demo2;
import org.springframework.stereotype.Component;
@Component
public class EatImpl2 implements Eat{
@Override
public void eatMeal() {
System.out.println("this is eatImpl2");
}
}
EatImpl3
package com.xueyou.demo2;
import org.springframework.stereotype.Component;
@Component
public class EatImpl3 implements Eat{
@Override
public void eatMeal() {
System.out.println("this is eatImpl3");
}
}
Animal
package com.xueyou.demo2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Animal {
@Autowired
private Eat eat;
public void eatDetail() {
eat.eatMeal();
}
}
App
package com.xueyou.demo;
import com.xueyou.demo2.Animal;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Hello world!
*/
@Configuration
@ComponentScan(basePackages = {"org.xueyou.demo","com.xueyou.demo","com.xueyou.demo2"})
public class App {
public static void main(String[] args) {
System.out.println("Hello World!");
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(com.xueyou.demo.App.class);
// Person p = applicationContext.getBean(Person.class);
// p.showMyBody();
Animal animal = applicationContext.getBean(Animal.class);
animal.eatDetail();
}
}
5、运行结果:
从运行结果上能够看出,现在出现的错误是NoUniqueBeanDefinitionException。
原因是这样的在@Autowired注解进行自动装配的时候,发现有三个类都满足要求,这个时候spring不能够从这三个bean中选择一个bean进行装配,从而出现异常。
解决方法:
1、使用@Primary注解
2、使用@Qualifier注解
3、自定义注解
前两种方法比较简单,就是类似这样
package com.xueyou.demo2;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
@Qualifier("firstEat")
public class EatImpl1 implements Eat {
@Override
public void eatMeal() {
System.out.println("this is eatImpl1");
}
}
package com.xueyou.demo2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Animal {
@Autowired
@Qualifier("firstEat")
private Eat eat;
public void eatDetail() {
eat.eatMeal();
}
}
再次运行会发现已经可以了。
这里主要介绍一下自定义注解的方式:
首先要新建注解。
package com.xueyou.demo2;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface EatAnno {
String value() default "";
}
使用自定义注解。
package com.xueyou.demo2;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
@EatAnno(value = "firstEat")
public class EatImpl1 implements Eat {
@Override
public void eatMeal() {
System.out.println("this is eatImpl1");
}
}
package com.xueyou.demo2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Animal {
@Autowired
@EatAnno(value = "firstEat")
private Eat eat;
public void eatDetail() {
eat.eatMeal();
}
}
运行结果: