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 自動裝配及其註解

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