Spring中实现自动装配的相关注解总结

一、自动装配

自动装配即为Spring利用依赖注入来完成对IOC容器中各个组件的依赖关系赋值。

Spring框架的五种自动装配模式:

  1. no:Spring框架的默认设置,在该设置下自动装配是关闭的。开发者需要自行在bean定义中用标签或注解来明确的设置依赖关系。
  2. byName:根据名称设置依赖关系来自动装配bean属性。
  3. byType:根据类型设置依赖关系来自动装配bean属性。
  4. constructor:构造器的自动装配和byType模式类似,但是仅仅适用于在容器中存在与构造器的参数相同类型的bean的情况,如果在容器中没有找到与构造器的参数类型一致的bean,那么将会抛出异常。
  5. autodetect:该模式自动探测使用构造器自动装配或者byType自动装配。首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。在Spring3.0之后已经被标记为@Deprecated,不建议使用。

二、自动装配相关注解

从Spring2.5开始,开始支持使用注解来自动装配Bean的属性。它允许更细粒度的自动装配,我们可以选择性的标注某一个属性来对其应用自动装配。Spring支持几种不同的应用于自动装配的注解。

  • Spring自带的@Autowired注解。
  • JSR-250的@Resource注解。
  • JSR-330的@Inject注解。

1.@Autowired

@Autowired注解默认优先按照类型(byType)去容器中找对应的组件。如果找到多个相同类型的组件,就将属性的名称作为组件的id去容器中查找同id的bean再进行赋值。

@Autowired注解可以标注在构造器,参数,方法,属性上。标注在方法位置可以不加@Autowired注解,方法参数是直接从容器中获取的。(即为constructor自动装配模式)

使用

下面通过一个例子来掌握@Autowired的作用:
创建Dao层person类

@Repository
public class PersonDao {
	public int flag=1;
	@Override
	public String toString() {
		return "PersonDao [flag=" + flag + "]";
	}
}

创建service层的personService类

@Service
public class PersonService {
	@Autowired
	PersonDao personDao;	
	@Override
	public String toString() {
		return "PersonService [personDao=" + personDao + "]";
	}
}

这里的PersonService 类还可以将@Autowired标注在不同的地方:属性对应的set方法构造方法。同样能实现将personDao类型的组件装配到PersonService类中。

@Service
public class PersonService {
	PersonDao personDao;
	@Override
	public String toString() {
		return "PersonService [personDao=" + personDao + "]";
	}
	public PersonService(@Autowired PersonDao personDao) {
		this.personDao=personDao;
	}
	}
}
@Service
public class PersonService {
	PersonDao personDao;
	@Override
	public String toString() {
		return "PersonService [personDao=" + personDao + "]";
	}
	@Autowired
	public void setPersonDao(PersonDao personDao) {
		this.personDao=personDao;
	}
}

创建配置类SpringConfigOfAutoWired类

@Configuration
@ComponentScan(value = {"com.learn.dao","com.learn.service"})
public class SpringConfigOfAutoWired {	
    @Bean
	PersonDao personDao2() {
		PersonDao personDao = new PersonDao();
		personDao.flag=2;
		return personDao;
	}
}

创建测试类AutoWiredTest

public class AutoWiredTest {
	@Test
	public void test() {
		//获取Spring的IOC容器
		AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfigOfAutoWired.class);
		//从容器中获取bean
	    String[] names= applicationContext.getBeanDefinitionNames();	
		for(String i:names) {
		    	System.out.println(i);
		 }
		PersonService service=applicationContext.getBean(PersonService.class);
        System.out.println(service);
	}
}

运行test()方法,查看控制台结果:
在这里插入图片描述
可以看到@Autowired默认注入的是personDao,对应属性名personDao。

默认情况下,它具有强制契约特性,其所标注的属性必须是可装配的。当容器中没有这个类型的组件但又不想影响容器的创建,可以使用@Autowired(required = false)

另外,当容器中有多个相同类型的组件时,如果定义的这个属性名在容器中没有对应的组件id,那么就会报NoUniqueBeanDefinitionException这个异常。这时使用@Qualifier注解就可以避免这种情况。

@Qualifier

@Qualifier注解的作用是指定需要装配的组件的id,相当于按照byName类型进行自动装配。 @Qualifier不能单独使用。

在 PersonService 类中添加注解@Qualifier("personDao2"),这样就指定了使用id为personDao2的组件来装配。

@Service
public class PersonService {
	
	@Qualifier("personDao2")
	@Autowired
	PersonDao personDao3;
	
	@Override
	public String toString() {
		return "PersonService [personDao=" + personDao3 + "]";
	}
}

再次运行测试方法test(),查看控制台输出:
在这里插入图片描述

@Primary

让Spring进行自动装配时,优先使用@Primary注解修饰的组件。使用这个注解也能避免使用属性名作为id来查找容器中的组件,下面删除前面添加的@Qualifier注解,在person2()方法上添加@Primary

@Configuration
@ComponentScan(value = {"com.learn.dao","com.learn.service"})
public class SpringConfigOfAutoWired {	
	@Primary
    @Bean(value = "personDao2")
	PersonDao personDao2() {
		PersonDao personDao = new PersonDao();
		personDao.flag=2;
		return personDao;
	}
}

这样自动装配时就会优先装配id为personDao2的组件。

2.@Resource

@Resource属于java规范中的注解,@Resource可以与@Autowired一样实现自动装配功能,默认是按照属性名的名称进行装配。可以通过@Resource(name = “”)指定组件的id,如果byName方式找不到,就使用byType方式查找。但是不支持搭配@Primary和@Qualifier("")使用和不支持@Autowired的required功能。

使用

修改类PersonService 改用@Resource进行自动装配

@Service
public class PersonService {
	//@Qualifier("personDao2")
	//@Autowired(required = false)
	@Resource
	PersonDao personDao3;
	
	@Override
	public String toString() {
		return "PersonService [personDao=" + personDao3 + "]";
	}
}

这样也是能成功装配组件。这里如果添加@Primary和@Qualifier("")来指定组件,虽然不会报错但是是不起作用的。

3.@Inject

@Inject属于java规范中的注解,同样提供与@Autowired一样实现自动装配功能,支持搭配@Primary和@Qualifier("")注解使用,但是没有支持required=false的功能。

@Inject是根据类型进行自动装配的,找到后以属性名作为id来匹配要装配的组件,如果存在多个相同类型的组件时或需要按名称进行装配,则需要配合@Named;

需要在pom.xml中添加以下依赖才能使用:

	<dependency>
		  <groupId>javax.inject</groupId>
		  <artifactId>javax.inject</artifactId>
		  <version>1</version>
	</dependency>

使用

@Service
public class PersonService {	
	//@Qualifier("personDao2")
	//@Autowired(required = false)
	//@Resource
	@Named("personDao2")
	@Inject
	PersonDao personDao3;	
	@Override
	public String toString() {
		return "PersonService [personDao=" + personDao3 + "]";
	}
}

这样同样能成功装配PersonDao类型的id为personDao2的组件。

三、总结

  1. @Autowired是spring自带的,@Resource是JSR-250规范实现的,@Inject是JSR-330规范实现的,需要对应导入不同的包。

  2. @Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性

  3. @Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的

  4. @Autowired如果需要按照名称匹配需要和@Qualifier一起使用,@Inject和@Name一起使用

  5. @Inject支持搭配@Primary和@Qualifier("")注解一起使用


参考:annotation之@Autowired、@Inject、@Resource三者区别

拓展阅读:
彻底搞明白Spring中的自动装配和Autowired
XML配置文件中实现自动装配——Spring 自动装配及其注解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章