四、註解配置IOC、DI
1、註解 @Component
我們這裏有個類 Person
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.ys.annotation;
public class Person {
private int pid;
private String pname;
private String psex;
public int getPid() {
return pid;
}
public void setPid( int pid) {
this .pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this .pname = pname;
}
public String getPsex() {
return psex;
}
public void setPsex(String psex) {
this .psex = psex;
}
}
|
如果我們不使用註解,通過前面講解的,要想讓 Spring 容器幫我們產生 Person 對象,我們要進行如下配置:
applicationContext.xml 配置:
1 |
<bean id= "person" class = "com.ys.annotation.Person" ></bean>
|
如果使用註解呢?
第一步:在 applicationContext.xml 中引入命名空間
這裏我們簡單講解一下這裏引入的命名空間,簡單來說就是用來約束xml文件格式的。第一個 xmlns:context ,這表示標簽格式應該是 <context:標簽名>
第二步:在 applicationContext.xml 文件中引入註解掃描器
1 2 |
<!-- 組件掃描,掃描含有註解的類 -->
<context:component-scan base- package = "com.ys.annotation" ></context:component-scan>
|
base-package:表示含有註解類的包名
如果掃描多個包,則上面的代碼書寫多行,改變 base-package 裏面的內容即可!
第三步:在 Person 類中添加註解@Component
第四步:測試
1 2 3 4 5 6 7 8 9 10 |
@Test
public void testAnnotation(){
//1、啟動 spring 容器
//2、從 spring 容器中取出數據
//3、通過對象調用方法
ApplicationContext context =
new ClassPathXmlApplicationContext( "applicationContext.xml" );
Person person = (Person) context.getBean( "person" );
System.out.println(person.getPname());
}
|
如果看完上面的註解配置,你一臉懵逼,那沒關系,我們下面來詳細講解。
@Component
如果一個類上加了@Component註解,就會進行如下的法則
如果其value屬性的值為""
@Component
public class Person {}
等價於
<bean id="person" class="..Person">
如果其value屬性的值不為""
@Component("p")
public class Person {}
等價於
<bean id="p" class="..Person">
那麽這就很好理解測試程序中,我們直接 context.getBean("person") 這樣寫。
回到頂部
2、@Repository @Service @Controller
此外:下面三個註解是 @Component 註解的衍生註解,功能一樣
1 2 3 |
@Repository :dao層
@Service :service層
@Controller :web層
|
回到頂部
3、註解 @Resource
@Resource 註解,它可以對類成員變量、方法及構造函數進行標註,完成自動裝配的工作。 通過 @Resource 的使用來消除 set ,get方法。
首先創建一個 學生類 Student.java
然後在 Person 類中添加一個屬性 Student
那麽我們如何獲取 Person 對象,並調用 showStudent()方法呢?這個問題簡化就是如何給屬性 Student 實例化,也就是依賴註入
不使用註解:
1 2 3 4 |
<property name= "students" >
<ref bean= "student" />
</property>
<bean id= "student" class = "com.ys.annotation_di.Student" ></bean>
|
使用註解:
@Resource註解以後,判斷該註解name的屬性是否為""(name沒有寫)
①、如果沒有寫name屬性,則會讓屬性的名稱的值和spring配置文件bean中ID的值做匹配(如果沒有進行配置,也和註解@Component進行匹配),如果匹配成功則賦值,如果匹配不成功,則會按照spring配置文件class類型進行匹配,如果匹配不成功,則報錯
②、如果有name屬性,則會按照name屬性的值和spring的bean中ID進行匹配,匹配成功,則賦值,不成功則報錯
回到頂部
4、註解 @Autowired
功能和註解 @Resource 一樣,可以對類成員變量、方法及構造函數進行標註,完成自動裝配的工作。只不過註解@Resource 是按照名稱來進行裝配,而@Autowired 則是按照類型來進行裝配。
第一步:創建接口 PersonDao
1 2 3 4 5 6 7 |
package com.ys.autowired;
public interface PersonDao {
public void savePerson();
}
|
第二步:創建一個接口實現類 PersonDaoImplOne
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.ys.autowired;
import org.springframework.stereotype.Component;
@Component ( "personDaoImplOne" )
public class PersonDaoImplOne implements PersonDao{
@Override
public void savePerson() {
System.out.println( "save Person One" );
}
}
|
第三步:創建PersonService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.ys.autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service ( "personService" )
public class PersonService{
@Autowired
private PersonDao personDao;
public void savePerson() {
this .personDao.savePerson();
}
}
|
註意:這裏我們在 private PesronDao personDao 上面添加了註解 @Autowired,它首先會根據類型去匹配,PersonDao 是一個接口,它的實現類是 PesronDaoImpOne,那麽這裏的意思就是:
PersonDao personDao = new PersonDaoImpOne();
那麽問題來了,如果 PersonDao 的實現類有多個呢?我們創建第一個實現類 PersonDaoImpTwo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.ys.autowired;
import org.springframework.stereotype.Component;
@Component ( "personDaoImplTwo" )
public class PersonDaoImplTwo implements PersonDao{
@Override
public void savePerson() {
System.out.println( "save Person Two" );
}
}
|
如果還是向上面那樣寫,那麽測試就會報錯。怎麽解決呢?
第一種方法:更改名稱
第二種方法:@Autowired 和 @Qualifier("名稱") 配合使用
在使用@Autowired時,首先在容器中查詢對應類型的bean
如果查詢結果剛好為一個,就將該bean裝配給@Autowired指定的數據
如果查詢的結果不止一個,那麽@Autowired會根據名稱來查找。
如果查詢的結果為空,那麽會拋出異常。解決方法時,使用required=false
四、註解配置IOC、DI