文章目錄
(一)常用IOC注解按作用分類
(二)用于建立對象的注解
(三)由Component衍生的注解
(四)自動按照類型注入
(五)用于注入資料的注解
(六)改變作用範圍的注解
(七)與生命周期相關的注解
(一)常用IOC注解按作用分類
學習基于注解的 IoC 配置,大家腦海裡首先得有一個認知:
即注解配置和 xml 配置要實作的功能都是一樣的(隻是形式不一樣),都是要降低程式間的耦合
關于實際的開發中到底使用xml還是注解,每家公司有着不同的使用習慣,是以這兩種配置方式我們都需要掌握
建立一個普通的maven項目,并且被bean.xml的配置注釋掉
曾經XML的配置:
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"
scope="" init-method="" destroy-method="">
<property name="" value="" | ref=""></property>
</bean>
注解的分類:
- 用于建立對象的
作用:他們的作用就和在XML配置檔案中編寫一個<bean>标簽實作的功能是一樣的
- 用于注入資料的
作用:他們的作用就和在xml配置檔案中的bean标簽中寫一個<property>标簽的作用是一樣的
- 用于改變作用範圍的
作用:他們的作用就和在bean标簽中使用scope屬性實作的功能是一樣的
- 和生命周期相關的
作用:他們的作用就和在bean标簽中使用init-method和destroy-methode的作用是一樣的
(二)用于建立對象的注解
使用建立對象的注解效果跟在XML配置檔案中編寫一個
<bean>标簽
實作的功能是一樣的
@Component:
作用:用于把目前類對象存入spring容器中
屬性:
value:用于指定bean的id。當我們不寫時,它的預設值是目前類名,且首字母改小寫
嘗試使用
@Component
注解,不加任何參數,預設就是首字母改小寫的類名
但是會發現報錯了,原因如下:
(我們已經提前把bean.xml的相關标簽都注釋掉了)
//1.擷取核心容器對象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
ClassPathXmlApplicationContext初始化容器時會把bean.xml中聲明的标簽下的類都建立到容器中
但是因為bean.xml并不知道哪一個類加上注解了,是以無法建立對象
我們要在bean.xml告知spring在建立容器時要掃描的包
配置所需要的标簽不是在bean.xml的限制中,而是在一個名稱為context的名稱空間的限制中
然後加上标簽指明要掃描的包
運作效果如下:
我們可以自定義value的值
當然注解隻有一個參數,且參數為value時可以使用省略寫法
(三)由Component衍生的注解
@Controller:一般用在表現層
@Service:一般用在業務層
@Repository:一般用在持久層
以上三個注解他們的作用和屬性與@Component是一模一樣
他們三個是spring架構為我們提供明确的三層使用的注解,使我們的三層對象更加清晰
原理:其實接口就是類,上面的Component類是父類,現在這三個分别是它的子類,隻繼承,不重寫
我們接下來改寫業務層的注解,讓它更規範,并且增加持久層的注解
運作試試
(四)自動按照類型注入
我們上一篇部落格提到一個問題:業務層實作類如何調用持久層的方法?
我們最後是配置了xml解決這個問題,現在嘗試用注解去解決
可以使用
@Autowired
注解實作自動按照類型注入,如下:
運作試試:
原理如下:
容器中有唯一的一個bean對象類型和要注入的變量類型比對,就可以注入成功
詳細過程:首先會找到實作類,但是因為實作類繼承了接口,是以可以把實作類看作接口(多态)
那麼如果ioc容器中有多個類型比對呢?
預設情況下會報錯,如下:
但是下面這兩種情況也是有多個比對類型,但是卻不報錯,如下:
總結:
- 如果有唯一一個比對時,就直接注入
-
如果有多個比對時,首先按照類型篩選出來比對的對象
然後使用變量名稱作為bean的id,然後繼續篩選
如果兩次篩選後有唯一比對的,可以注入成功;否則失敗
(五)用于注入資料的注解
使用注入資料注解的效果跟在xml配置檔案中的bean标簽中寫一個
<property>标簽
的作用是一樣的
@Autowired:
作用:
自動按照類型注入
如果容器中有唯一的一個bean對象類型和要注入的變量類型比對,就可以注入成功
如果ioc容器中沒有任何bean的類型和要注入的變量類型比對,則報錯
如果ioc容器中有多個類型比對時(上面有詳解,這裡不再重複)
出現位置:
可以是變量上,也可以是方法上
細節:
在使用注解注入時,set方法就不是必須的了
===================================================================================
@Qualifier:
作用:
在按照類中注入的基礎之上再按照名稱注入
它在給類成員注入時不能單獨使用;但是在給方法參數注入時可以(見:Spring之新注解(六))
屬性:
value:用于指定注入bean的id
===================================================================================
@Resource
作用:
直接按照bean的id注入。它可以獨立使用
屬性:
name:用于指定bean的id
以上三個注入都隻能注入其他bean類型的資料,而基本類型和String類型無法使用上述注解實作
另外,集合類型的注入隻能通過XML來實作
===================================================================================
@Value
作用:
用于注入基本類型和String類型的資料
屬性:
value:用于指定資料的值。它可以使用spring中SpEL(也就是spring的el表達式)
SpEL的寫法:${表達式}
先看看
@Qualifier
,它可以在按照類中注入的基礎之上再按照名稱注入
一般用來處理多種比對結果的情況;另一種accountDao2的情況就不示範了
注意:在給類成員注入時,必須與Autowired注解配對使用,不能單獨使用,否則會空指針異常
(在給方法參數注入時可以單獨使用,後面會介紹)
我們單獨使用
@Autowired
時需要改變變量名;使用
@Qualifier
時又不能單獨使用,那有沒有更友善的注解呢?下面介紹
@Resource
其中的name屬性用于指定bean的id,此時不是value屬性了,是以不能使用省略寫法
但是
@Resource
也存在缺點,包括前面的
@Autowired
和
@Qualifier
都存在一些共同的缺點:
- 這三個注解都隻能注入其他bean類型的資料,而基本類型和String類型無法使用上述注解實作
- 另外,集合類型的注入隻能通過XML來實作
集合類型無法用注解注入我們可以略過,但是我們該如何用注解注入基本類型和String類型呢?我們可以用
@Value
注解實作
value:用于指定資料的值。它可以使用spring中SpEL(也就是spring的el表達式)
SpEL的寫法:${表達式}
具體用法這裡不再展示了,詳情可以見後面的綜合案例
(六)改變作用範圍的注解
使用改變作用範圍的注解的作用跟在
bean标簽
中使用scope屬性實作的功能是一樣的
@Scope:
作用:用于指定bean的作用範圍
屬性:
value:指定範圍的取值。常用取值:singleton(單例)、prototype(多例)
注意:不寫該注解的話,預設情況下是單例的
下面示範一下多例的情況
(七)與生命周期相關的注解
使用與生命周期相關的注解的作用跟在
bean标簽
中使用init-method和destroy-methode的作用是一樣的
@PreDestroy
作用:用于指定銷毀方法
@PostConstruct
作用:用于指定初始化方法