Spring純注解開(kāi)發(fā)模式讓開(kāi)發(fā)簡(jiǎn)化更簡(jiǎn)化
一.注解開(kāi)發(fā)
以前跟老韓學(xué)習(xí)SE時(shí)他就說(shuō):
注解本質(zhì)是一個(gè)繼承了Annotation 的特殊接口,其具體實(shí)現(xiàn)類(lèi)是Java 運(yùn)行時(shí)生成的動(dòng)態(tài)代理類(lèi)。
而我們通過(guò)反射獲取注解時(shí),返回的是Java 運(yùn)行時(shí)生成的動(dòng)態(tài)代理對(duì)象$Proxy1。通過(guò)代理對(duì)象調(diào)用自定義注解(接口)的方法,會(huì)最終調(diào)用AnnotationInvocationHandler 的invoke 方法。該方法會(huì)從memberValues 這個(gè)Map 中索引出對(duì)應(yīng)的值。而memberValues 的來(lái)源是Java 常量池。
二.注解定義Bean
注解開(kāi)發(fā)前,配置Bean時(shí)是在xml里將class分別寫(xiě)在Bean標(biāo)簽里,然后起id,就像這樣
<bean id="a" class="yu7daily.Dao.Daoimpl.A" />
注解開(kāi)發(fā)后,配置Bean時(shí)首先將xml里的<Bean>標(biāo)簽刪掉,然后在類(lèi)上添加@Component注解即可
@Component("a") public class A implements AA { public void save() { System.out.println("book dao save ..." ); } }
在xml文件中來(lái)寫(xiě)一個(gè)掃描包的注解標(biāo)簽,對(duì)象就裝進(jìn)IOC容器里了
<context:component-scan base-package="yu7daily.Dao"/>
component-scan:component意為組件,scan意為掃描
包路徑越多,掃描的范圍越小速度越快·包路徑越少,掃描的范圍越大速度越慢
最后直接從容器獲取對(duì)象
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); A aa = (A) ctx.getBean("a"); bookService.save(); }
這里要注意的是:由于接口無(wú)法創(chuàng)建對(duì)象,所以別把注解寫(xiě)在接口上??!
注解真是神奇啊,他和原先的xml里的Bean到底是什么關(guān)系呢?
三.衍生注解
對(duì)于@Component還有衍生的三個(gè)注解:
@Controller、@Service、@Repository
結(jié)合與MVC的模式分別起到了補(bǔ)充的作用,方便我們后期在編寫(xiě)類(lèi)的時(shí)候能很好的區(qū)分出這個(gè)類(lèi)是屬于表現(xiàn)層、業(yè)務(wù)層還是數(shù)據(jù)層的類(lèi)
四.純注解開(kāi)發(fā)模式
顧名思義,純注解的模式就是摒棄以前的配置操作,全部由注解來(lái)完成
@Configuration:類(lèi)注解,設(shè)置該類(lèi)為Spring配置類(lèi)
@ComponentScan:類(lèi)注解,設(shè)置Spring配置類(lèi)掃描路徑
1.寫(xiě)一個(gè)配置類(lèi),通過(guò)注解@Configuration來(lái)標(biāo)注該類(lèi)為配置類(lèi)、@ComponentScan來(lái)配置包掃描
這樣就替換掉了<context:component-scan base-package="yu7daily.Dao"/>
@Configuration @ComponentScan("yu7daily") public class Config {...}
然后類(lèi)就被放進(jìn)了Bean里,通過(guò)
ApplicationContext acct = new AnnotationConfigApplicationContext(Config.class);
就可以得到Bean
一頓操作下來(lái)我們通過(guò)一個(gè)Java類(lèi)替換掉了Spring的核心配置文件,完全告別了xml!
配置Bean作用域
我們知道,通過(guò)Bean造的對(duì)象默認(rèn)都是單例的,如何造出非單例的Bean?
通過(guò)@Scope注解即可,屬性值(默認(rèn)singleton(單例),可選值prototype(非單例))
@Component("a") @Scope("prototype") public class A implements AA { public void save() { System.out.println("hello~"); } }
五.注解實(shí)現(xiàn)注入
Set注入的原理是通過(guò)set方法在容器內(nèi)部將一個(gè)類(lèi)設(shè)置到另一個(gè)類(lèi)中,這也是比較常用的方法。那么在純注解開(kāi)發(fā)的模式下如何實(shí)現(xiàn)注入呢?
@Service public class A implements AA { @Autowired private B b; }
如上,通過(guò)在屬性上添加注解@Autowired就實(shí)現(xiàn)了將B注入到A中
1.自動(dòng)裝配
在前面寫(xiě)配置文件的階段autowire屬性可以開(kāi)啟自動(dòng)裝配,通常使用按類(lèi)型裝配autowire="byType"
對(duì)于自動(dòng)裝配的理解:在set注入的基礎(chǔ)上配置文件寫(xiě)的更加簡(jiǎn)潔,因?yàn)樵赟ervice里寫(xiě)了set方法把Dao的對(duì)象搞到了Service里,所以在配置Bean的時(shí)候我們通過(guò)自動(dòng)裝配,在xml文件里實(shí)現(xiàn)了Service和Dao自動(dòng)結(jié)合,不再需要去Service里通過(guò)property標(biāo)簽來(lái)指定相應(yīng)的name-ref
自動(dòng)裝配基于反射設(shè)計(jì)創(chuàng)建對(duì)象并通過(guò)暴力反射為私有屬性進(jìn)行設(shè)值普通反射只能獲取public修飾的內(nèi)容,暴力反射除了獲取public修飾的內(nèi)容還可以獲取private修改的內(nèi)容,注解的模式就是體現(xiàn)形式的變式,自動(dòng)裝配本質(zhì)還是沒(méi)有變
2.按名稱(chēng)注入
針對(duì)相同類(lèi)型的Bean如果IOC中存在多個(gè),那按照類(lèi)型注入一定會(huì)出錯(cuò),就像這樣
我通過(guò)注解注入的方式,注入了兩個(gè)AA的實(shí)現(xiàn)類(lèi)到B中,然后通過(guò)B來(lái)調(diào)用AA接口下的save()方法講道理應(yīng)該輸出“hello~A”,結(jié)果出現(xiàn)了NoUniqueBeanDefinitionException
可見(jiàn)按照類(lèi)型注入還是存在弊端啊,如何解決?
我們可以通過(guò)按照名稱(chēng)注入的方式:
當(dāng)根據(jù)類(lèi)型在容器中找到多個(gè)bean,注入?yún)?shù)的屬性名又和容器中bean的名稱(chēng)不一致,這個(gè)時(shí)候該如何解決,就需要使用到注解@Qualifier 來(lái)指定注入哪個(gè)名稱(chēng)的bean對(duì)象,在不修改其他條件下,就像這樣
@Repository("b") public class B implements BB { @Autowired @Qualifier("a") //注入指定的對(duì)象名稱(chēng) private AA aa; public void save() { aa.save(); } }
隨著運(yùn)行結(jié)果,輸出了A的成員方法,說(shuō)明注入成功!
值得注意的是:@Qualifier不能獨(dú)立使用,必須和@Autowired一起使用?。。?/p>
3.簡(jiǎn)單數(shù)據(jù)注入
通過(guò)注解@value可以實(shí)現(xiàn)簡(jiǎn)單數(shù)據(jù)注入,以String類(lèi)型數(shù)據(jù)為例
@Repository("a") public class A implements AA { @Value("hello java") private String str; public void save() { System.out.println(str); } }
運(yùn)行結(jié)果:hello
其實(shí)上述操作看起來(lái)有點(diǎn)多此一舉,@value主要還是為了讀取配置文件而服務(wù)的
4.讀取properties配置文件
首先在配置類(lèi)上寫(xiě)上注解@PropertySource用來(lái)指明讀取目錄下的哪個(gè)文件
@Configuration @ComponentScan("yu7daily") @PropertySource("test.properties") public class SpringConfig { }
在相應(yīng)的屬性上配置@Value注解即可完成配置文件屬性的讀取
PS:配置文件內(nèi)容——name=lanyangyang
@Repository("a") public class A implements AA { @Value("${name}") private String str; public void save() { System.out.println(str); } }
運(yùn)行結(jié)果:lanyangyang
其實(shí)讀取配置文件連接數(shù)據(jù)庫(kù)也是這套操作
六.Spring整合MyBatis
在配置好MyBatis的基礎(chǔ)上(不熟悉的可以去看一下以前寫(xiě)的MyBatis文章),Spring的整合工作就變的非常簡(jiǎn)單,主要工作就是管理MyBatis中的SqlSessionFactory和Mapper接口的掃描
1.首先導(dǎo)入兩個(gè)整合需要的的jar包:
<artifactId>spring-jdbc</artifactId>
和13<artifactId>mybatis-spring</artifactId>
2.配置數(shù)據(jù)源對(duì)象
2.創(chuàng)建主配置類(lèi)
@Configuration @ComponentScan("yu7daily") @PropertySource("classpath:jdbc.properties") 4@Import({JdbcConfig.class,MybatisConfig.class}) public class SpringConfig {...}
3.創(chuàng)建MyBatis配置類(lèi)并獲得SqlSessionFactory對(duì)象
4.最后在主函數(shù)中得到對(duì)應(yīng)的Bean即可進(jìn)行對(duì)數(shù)據(jù)層的操作
ApplicationContext ACC = new AnnotationConfigApplicationContext(SpringConfig.class); AccountService acc = ACC.getBean(AccountService.class);
這工作量比原來(lái)是不是簡(jiǎn)單多了,簡(jiǎn)直太哇塞了
到此這篇關(guān)于Spring純注解開(kāi)發(fā)模式讓開(kāi)發(fā)簡(jiǎn)化更簡(jiǎn)化的文章就介紹到這了,更多相關(guān)Spring注解開(kāi)發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot高級(jí)教程之Spring Boot連接MySql數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了Spring Boot高級(jí)教程之Spring Boot連接MySql數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10使用自定義注解實(shí)現(xiàn)redisson分布式鎖
這篇文章主要介紹了使用自定義注解實(shí)現(xiàn)redisson分布式鎖,具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02java多線(xiàn)程編程學(xué)習(xí)(線(xiàn)程間通信)
下面小編就為大家?guī)?lái)一篇java多線(xiàn)程編程學(xué)習(xí)(線(xiàn)程間通信)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09Leetcode常見(jiàn)鏈表問(wèn)題及代碼示例
這篇文章主要介紹了Leetcode常見(jiàn)鏈表問(wèn)題及代碼示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11基于XML的MyBatis的環(huán)境搭建過(guò)程詳解(IDEA)
這篇文章主要介紹了基于XML的MyBatis的環(huán)境搭建過(guò)程詳解(IDEA),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11java基于正則表達(dá)式實(shí)現(xiàn)時(shí)間日期的常用判斷操作實(shí)例
這篇文章主要介紹了java基于正則表達(dá)式實(shí)現(xiàn)時(shí)間日期的常用判斷操作,簡(jiǎn)單說(shuō)明了正則表達(dá)式常用元字符含義并結(jié)合實(shí)例形式分析了java基于正則表達(dá)式針對(duì)常用日期時(shí)間格式的判斷操作技巧,需要的朋友可以參考下2017-10-10spring啟動(dòng)錯(cuò)誤Singleton bean creation not al
本文主要介紹了spring啟動(dòng)錯(cuò)誤Singleton bean creation not allowed while the singletons of this factory are indestruction,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07