Spring5复习:@Autowired、@Bean和@Qualifier等注解的测试

1.声明

当前内容主要用于本人复习Spring5的@Autowired、@Bean和@Qualifier等注解,以及其中的区别

Spring5.1.5版本

本内容采用注解配置和组件扫描方式

本次使用的pom.xml依旧相同
<context:annotation-config />
<context:component-scan base-package=“com.hy.java.spring.annotation.qualifier” />

2.测试

自动注入bean

MovieFinder.java

public class MovieFinder {
	public int id;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public void find() {
		System.out.println("current movie finder find a moviee ....");
	}
}

QualifierAnnotationConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QualifierAnnotationConfig {

	@Bean
	public MovieFinder getMainMovieFinder() {
		MovieFinder mainMovieFinder = new MovieFinder();
		mainMovieFinder.setId(11111);
		return mainMovieFinder;
	}
}

SimpleMovieLister .java


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("simpleMovieLister")
public class SimpleMovieLister {

	@Autowired
	private MovieFinder mainMovieFinder;
	
	public MovieFinder getMainMovieFinder() {
		return mainMovieFinder;
	}

	public void setMainMovieFinder(MovieFinder mainMovieFinder) {
		this.mainMovieFinder = mainMovieFinder;
	}
}

QualifierAnnotationTest .java


/**
 * @description 
 * @author admin
 *
 */
public class QualifierAnnotationTest {
	public static void main(String[] args) {
		String xml = "/com/hy/java/spring/annotation/qualifier/applicationContext.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(xml);
		SimpleMovieLister simpleMovieLister = context.getBean("simpleMovieLister", SimpleMovieLister.class);
		System.out.println(simpleMovieLister);
		System.out.println("mainMovieFinder id==>"+simpleMovieLister.getMainMovieFinder().getId());
	}
}

1.当只有@Autowired且IOC容器中只有一个对应类型的bean时,那么注入成功!

com.hy.java.spring.annotation.qualifier.SimpleMovieLister@6156496
mainMovieFinder id==>11111

2.当只有@Autowired且IOC容器中有两个或两个以上对应类型的bean时,那么注入失败!(抛出异常)
此时修改当前的QualifierAnnotationConfig.java中的代码:

	@Bean
	public MovieFinder getMainMovieFinder() {
		MovieFinder mainMovieFinder = new MovieFinder();
		mainMovieFinder.setId(11111);
		return mainMovieFinder;
	}
	
	// 这是添加的@Bean
	@Bean
	public MovieFinder getMovieFinder() {
		MovieFinder mainMovieFinder = new MovieFinder();
		mainMovieFinder.setId(22222);
		return mainMovieFinder;
	}

再次测试的结果为:报错

No qualifying bean of type ‘com.hy.java.spring.annotation.qualifier.MovieFinder’ available: expected single matching bean but found 2: getMainMovieFinder,getMovieFinder

解决本问题有:1.通过设置@Bean(“beanName”),且beanName对应SimpleMovieLister.java中的属性名称完全一致可以注入成功!

3.当只有@Autowired且IOC容器中有两个或两个以上对应类型的bean时,如果配置了@Bean(“beanName”),默认可以通过beanName的方式注入(自动查找setBeanName方法),如果有那么成功,否则报错

此时修改2中的文件QualifierAnnotationConfig.java中的内容的@Bean为其添加自定义名称,修改为

	@Bean(name = "mainMovieFinder")
	public MovieFinder getMainMovieFinder() {
		MovieFinder mainMovieFinder = new MovieFinder();
		mainMovieFinder.setId(11111);
		return mainMovieFinder;
	}


	@Bean(name = "movieFinder")
	public MovieFinder getMovieFinder() {
		MovieFinder mainMovieFinder = new MovieFinder();
		mainMovieFinder.setId(22222);
		return mainMovieFinder;
	}

再次启动发现成功!

com.hy.java.spring.annotation.qualifier.SimpleMovieLister@37e547da
mainMovieFinder id==>11111

通过@Bean中的beanName方式自动注入,再次修改2中的文件SimpleMovieLister.java中的内容

	@Autowired
	private MovieFinder mainMovieFinder;

	public MovieFinder getMainMovieFinder() {
		return mainMovieFinder;
	}

	public void setMainMovieFinder(MovieFinder mainMovieFinder) {
		this.mainMovieFinder = mainMovieFinder;
	}

	// 这是新添加的注入属性
	@Autowired
	private MovieFinder movieFinder;

	public MovieFinder getMovieFinder() {
		return movieFinder;
	}

	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}

在测试中添加:System.out.println(“movieFinder id==>”+simpleMovieLister.getMovieFinder().getId());
测试结果:成功!(此时的@Bean的beanName和注入的属性名称完全一致)

com.hy.java.spring.annotation.qualifier.SimpleMovieLister@6107227e
mainMovieFinder id==>11111
movieFinder id==>22222

如果@Bean中的beanName和注入的属性不一致那么报错:修改上面的文件SimpleMovieLister.java中的属性movieFinder为movieFinder2

测试结果:报错!

Error creating bean with name ‘simpleMovieLister’: Unsatisfied dependency expressed through field ‘movieFinder2’;

4.当只有@Autowired且IOC容器中有两个或两个以上对应类型的bean时,如果配置有@Qualifier(“beanName”),那么默认就是按照beanName找,如果没有则报错(一般和@Bean的名称一致)

此时只要添加@Qualifier(“beanName”)方式就可以解决3中的问题,修改SimpleMovieLister.java中的内容

@Autowired
	private MovieFinder mainMovieFinder;

	public MovieFinder getMainMovieFinder() {
		return mainMovieFinder;
	}

	public void setMainMovieFinder(MovieFinder mainMovieFinder) {
		this.mainMovieFinder = mainMovieFinder;
	}

	@Autowired
	@Qualifier("movieFinder") // 新添加的注解
	private MovieFinder movieFinder2;

	public MovieFinder getMovieFinder2() {
		return movieFinder2;
	}

	public void setMovieFinder2(MovieFinder movieFinder2) {
		this.movieFinder2 = movieFinder2;
	}

3.总结

  1. @Autowired一般是先按照类型注解
    1. 如果类型不存在则报错,然后如果只有一个类型则注入
    2. 如果存在两个以上的类型,可以按照@Bean的beanName需要注入的属性名称一致的方式注入
    3. 如果存在两个以上的类型,且@Bean的beanName和需要注入的属性名称不一致,那么报错
  2. @Bean一般用在方法上面,默认返回一个对象并注入到IOC容器中,可以设置beanName
  3. @Qualifier一般和@Autowired一起连用,采用@Bean的beanName注入,如果找不到则报错

版权声明:本文为weixin_45492007原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。