一、@Autowired注解的普通用法
1、可以将@Autowired注解放在成员变量上;
@Autowired
private StudentDao studentDao;
2、可以将@Autowired注解放在setter方法上;
@Autowired
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
3、可以将@Autowired注解放在构造器上;
@Autowired
public StudentServiceImpl(StudentDao studentDao) {
this.studentDao = studentDao;
}
默认情况下,如果找不到合适的bean将会导致autowiring失败抛出异常,这种时候,可以通过下面的方式避免:
设置@Autowired注解的required属性为false,这种时候即使没有找到合适的bean也不会抛出任何异常。虽然在配置的时候允许属性为空(即找不到对应的bean),但同样的要在使用的使用判断该属性是否为空,否则可能会在使用使抛出空指针异常
@Autowired(required = false)
private StudentDao studentDao;
每个类只能有一个构造器被标记为required=true,当设置@Autowired注解的required属性为true时,可以使用@Required注解:
@Required注解适用于bean属性的setter方法,这个注解仅仅标识,受影响的bean属性必须在配置是被填充,通过在bean定义或者通过自动装配一个明确的属性值。
@Autowired注解的入门使用示例
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 自动扫描包下的Bean并注册到IOC容器中 -->
<context:component-scan base-package="com.bxp.annotation"/>
</beans>
package com.bxp.annotation;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
public interface StudentDao {
public void say(String text);
}
package com.bxp.annotation;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@Repository
public class StudentDaoImpl implements StudentDao {
public void say(String text){
System.out.println("StudentDao:" + text);
}
}
package com.bxp.annotation;
public interface StudentService {
public void serviceSay(String text);
}
@Service
public class StudentServiceImpl implements StudentService{
// @Autowired
private StudentDao studentDao;
// @Autowired
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
@Autowired
public StudentServiceImpl(StudentDao studentDao) {
this.studentDao = studentDao;
}
public void serviceSay(String text){
System.out.println("StudentServiceImpl:" + text);
studentDao.say(text + "StudentServiceImpl:" + this.hashCode());
}
}
@Test
public void text(){
StudentService studentService = super.getBean("studentServiceImpl");
studentService.serviceSay("Autowired test\t");
}
二、Autowired注解的进阶使用
1、可以使用@Autowired注解那些众所周知的解析依赖性接口,比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPublisher,MessageSource,如下示例:
public class AutoWiringDao {
@Autowired
private ApplicationContext applicationContext;
public void say(String word){
……
}
}
2、可以通过添加注解给需要该类型的数组或者集合字段,以提供ApplicationContext中的所有特定类型的bean,并且如果bean有@Order注解或者实现Order接口,按照Order的先后顺序注入,如下面两个示例:
在Set上使用@Autowired注解
@Autowired
private Set<InterfaceBean> set;
public Set<InterfaceBean> getSet() {
return set;
}
public void setSet(Set<InterfaceBean> set) {
this.set = set;
}
在List上使用:
@Autowired
private List<InterfaceBean> interfaceBeanList;
public List<InterfaceBean> getInterfaceBeanList() {
return interfaceBeanList;
}
public void setInterfaceBeanList(List<InterfaceBean> interfaceBeanList) {
this.interfaceBeanList = interfaceBeanList;
}
3、可以用于装配key为String的Map,map的key就是bean的Id,map的值就是bean对象。
@Autowired
private Map<String, InterfaceBean> map;
public void setMap(Map<String, InterfaceBean> map) {
this.map = map;
}
public Map<String, InterfaceBean> getMap() {
return map;
}
示例:
<?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
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.bxp.autowiringmultibean"/>
</beans>
package com.bxp.autowiringmultibean;
public interface InterfaceBean {
public void say(String text);
}
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.channels.InterruptibleChannel;
@Order(2)
@Component
public class BeanImplOne implements InterfaceBean {
public void say(String text) {
System.out.println(this.getClass().getName() + "\t" + text);
}
}
package com.bxp.autowiringmultibean;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Order(1)
@Component
public class BeanImplTwo implements InterfaceBean {
public void say(String text) {
System.out.println(this.getClass().getName() + "\t" + text);
}
}
package com.bxp.autowiringmultibean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
public class AutowireMultiBean {
@Autowired
private List<InterfaceBean> interfaceBeanList;
@Autowired
private Map<String, InterfaceBean> map;
@Autowired
private Set<InterfaceBean> set;
public void setMap(Map<String, InterfaceBean> map) {
this.map = map;
}
public Map<String, InterfaceBean> getMap() {
return map;
}
public Set<InterfaceBean> getSet() {
return set;
}
public void setSet(Set<InterfaceBean> set) {
this.set = set;
}
public void say(){
System.out.println("list:");
for(InterfaceBean bean : interfaceBeanList){
bean.say("同类型的Bean注入List");
}
System.out.println("Map:");
for(Map.Entry entry : map.entrySet()){
((InterfaceBean)entry.getValue()).say(entry.getKey().toString() + "同类型的Bean注入Map");
}
}
public List<InterfaceBean> getInterfaceBeanList() {
return interfaceBeanList;
}
public void setInterfaceBeanList(List<InterfaceBean> interfaceBeanList) {
this.interfaceBeanList = interfaceBeanList;
}
}
@Test
public void multibeantest(){
AutowireMultiBean autowireMultiBean = super.getBean("autowireMultiBean");
autowireMultiBean.say();
}
程序输出内容如下:
list:
com.bxp.autowiringmultibean.BeanImplTwo 同类型的Bean注入List
com.bxp.autowiringmultibean.BeanImplOne 同类型的Bean注入List
Map:
com.bxp.autowiringmultibean.BeanImplOne beanImplOne同类型的Bean注入Map
com.bxp.autowiringmultibean.BeanImplTwo beanImplTwo同类型的Bean注入Map
注意: bean对象按照Order定义的先后顺序注入,所以list输出时完全按order定义的顺序输出,但是set和map在输出时,不会按照输入顺序进行输出,因为set(map)是无须的(这个是很重要的知识点,原因自己单独查看)。
@Autowired是由Spring BeanPostProcessor处理的,所以不能再自己的BeanPostProcessor或者BeanFactoryPostProcessor类型应用这个注解,这些类型必须通过XML或者Spring的@Bean注解加在
三、@Qualifier注解
按类型自动装配可能存在多个bean实例的情况,可以使用Spring的@Qualifier注解缩小范围(或指定唯一),也可以用于指定单独的构造器参数或方法参数
可用于注解集合类型变量
如果通过名字进行注解注入,主要使用的不是@Autowired(即使在技术上能够通过@Qualifier指定bean的名字),代替方法是使用JSR-250@Resource注解,它是通过其独特的名称来识别特定的目标(这是一个与所声明的类型是无关的匹配过程)
因语义差异,集合或者Map类型的bean无法通过@Autowired来注入,因为没有类型匹配到这样的bean,为这些bean使用@Resource注解,通过唯一名称引用集合或Map的bean。
@Autowired适用于fields,constructors,multi-argument methods这些允许在参数级别使用@Qualifier注解缩小范围的情况
@Resource适用于成员变量、只有一个参数的setter方法,所以在目标是构造器或一个多参数方法时,最好的方法是使用@Qualifier
示例:
部分代码以上面的示例为基础
@Component
public class QualifierBean {
@Autowired
@Qualifier("beanImplTwo")
private InterfaceBean interfaceBean;
public void say(){
System.out.println(interfaceBean.getClass().getName());
}
}
@Test
public void qualifierbeantest(){
QualifierBean qualifierBean = super.getBean("qualifierBean");
qualifierBean.say();
}
程序输出内容:
com.bxp.autowiringmultibean.BeanImplTwo