免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
騰訊程序員為你講解Spring的那幾百個(gè)注解,贈(zèng)java架構(gòu)師學(xué)習(xí)資料

本文我們來(lái)梳理一下Spring的那些注解,如下圖所示,大概從幾方面列出了Spring的一些注解:

如果此圖看不清楚也沒(méi)事,請(qǐng)運(yùn)行下面的代碼輸出所有的結(jié)果。

Spring目前的趨勢(shì)是使用注解結(jié)合Java代碼而不是配置來(lái)定義行為、屬性、功能、規(guī)則和擴(kuò)展點(diǎn),因此梳理注解也是梳理Spring功能點(diǎn)的很好的方式,全面的梳理可以補(bǔ)足我們知識(shí)點(diǎn)的漏洞。

查找所有注解

首先,我們來(lái)創(chuàng)建一個(gè)項(xiàng)目,使用SPRING INITIALIZR生成一個(gè)引入Spring各種組件的項(xiàng)目模板,然后引入如下工具包:

<dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.11</version></dependency>

通過(guò)這個(gè)反射工具包,我們可以創(chuàng)建一個(gè)Spring Boot應(yīng)用程序,以一行代碼打印出所有Spring框架的注解:

import org.reflections.Reflections;import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Component;import java.lang.annotation.Annotation;@Componentpublic class ScanAnnotationRunner implements CommandLineRunner { @Override  public void run(String... args)  throws Exception {  new Reflections('org.springframework') .getSubTypesOf(Annotation.class) .stream() .map(clazz->clazz.getName()) .sorted() .forEach(System.out::println); }}

輸出結(jié)果這里就不給出了,下面我們逐一進(jìn)行梳理其中的一些重要注解。

有關(guān)注解

Java的Annotation注解(類似于C#的Attribute特性),說(shuō)白了就是給代碼打上標(biāo)簽的能力。我們可以配置這個(gè)標(biāo)簽的保留階段,僅源代碼,源代碼+字節(jié)碼,源代碼+字節(jié)碼+運(yùn)行時(shí)。通過(guò)引入注解,我們可以簡(jiǎn)單快速賦予代碼生命力,大大提高代碼可讀性和擴(kuò)展性。注解本身不具有任何能力,只是一個(gè)標(biāo)簽,但是我們可以定義各種標(biāo)簽然后實(shí)現(xiàn)各種標(biāo)簽處理器來(lái)對(duì)類、方法、屬性甚至參數(shù)等進(jìn)行功能擴(kuò)展、功能開啟、屬性定義、行為定義、規(guī)則定義、關(guān)聯(lián)處理、元數(shù)據(jù)定義等等。在實(shí)現(xiàn)各種框架的時(shí)候,我們經(jīng)常會(huì)自定義標(biāo)簽方便框架使用者僅僅通過(guò)在合適的地方引入合適的注解來(lái)啟用(或自定義)框架的一些能力并應(yīng)用到我們的程序中。

不僅僅是框架的作者會(huì)大量使用注解,在之前的系列文章中我們也多次自定義注解,我們有通過(guò)定義@Metrics注解配合Spring AOP來(lái)為程序啟動(dòng)打點(diǎn)、日志、異常等功能,我們有通過(guò)定義@Sign注解配合Spring MVC的ResponseBodyAdvice進(jìn)行數(shù)據(jù)簽名功能,我們還經(jīng)常會(huì)定義各種自定義注解配合Spring MVC的HandlerMethodArgumentResolver進(jìn)行權(quán)限的校驗(yàn)等等功能。采用這種模式,我們的核心業(yè)務(wù)邏輯可以保持清晰干凈,通過(guò)注解配合AOP賦予代碼額外的能力。

你可能會(huì)說(shuō),注解還是有侵入性,我們需要耦合框架定義的那些注解,這個(gè)問(wèn)題其實(shí)是無(wú)解的,100%無(wú)侵入性也代表了可讀性的降低,代碼的功能和能力應(yīng)當(dāng)聚合在一起,這也就是為什么Spring現(xiàn)在也不建議采用XML來(lái)做配置。Java核心類庫(kù)并沒(méi)有什么注解,好在Spring已經(jīng)有了大量注解,而Spring也變?yōu)榱薐ava開發(fā)的標(biāo)準(zhǔn),所以其實(shí)我們很多時(shí)候如果希望自己的框架(RPC啥的)完全沒(méi)有侵入性的話可以借用Spring的那些注解@Autowired、@Controller、@Service等注解,配合各種包的規(guī)范其實(shí)我們可以對(duì)目標(biāo)元素的功能識(shí)別個(gè)八九不離十,完全有可能實(shí)現(xiàn)0侵入的功能增強(qiáng)。

有關(guān)如何實(shí)現(xiàn)自定義注解不贅述,這里我們簡(jiǎn)單回顧一下幾個(gè)元注解(注解的注解):

A. @Documented:將會(huì)在被此注解注解的元素的javadoc文檔中列出注解,一般都打上這個(gè)注解沒(méi)壞處

B. @Target:注解能被應(yīng)用的目標(biāo)元素,比如類、方法、屬性、參數(shù)等等,需要仔細(xì)思考

C. @Retention:僅在源碼保留,還是保留到編譯后的字節(jié)碼,還是到運(yùn)行時(shí)也去加載,超過(guò)90%的應(yīng)用會(huì)在運(yùn)行時(shí)去解析注解進(jìn)行額外的處理,所以大部分情況我們都會(huì)設(shè)置配置為RetentionPolicy.RUNTIME

D. @Inherited:如果子類沒(méi)有定義注解的話,能自動(dòng)從父類獲取定義了繼承屬性的注解,比如Spring的@Service是沒(méi)有繼承特性的,但是@Transactional是有繼承特性的,在OO繼承體系中使用Spring注解的時(shí)候請(qǐng)?zhí)貏e注意這點(diǎn),理所當(dāng)然認(rèn)為注解是能被子類繼承的話可能會(huì)引起不必要的Bug,需要仔細(xì)斟酌是否開啟繼承

E. @Repeatable:Java 8 引入的特性,通過(guò)關(guān)聯(lián)注解容器定義可重復(fù)注解,小小語(yǔ)法糖提高了代碼可讀性,對(duì)于元素有多個(gè)重復(fù)注解其實(shí)是很常見的事情,比如某方法可以是A角色可以訪問(wèn)也可以是B角色可以訪問(wèn),某方法需要定時(shí)任務(wù)執(zhí)行,要在A條件執(zhí)行也需要在B條件執(zhí)行

F. @Native:是否在.h頭文件中生成被標(biāo)記的字段,除非原生程序需要和Java程序交互,否則很少會(huì)用到這個(gè)元注解

現(xiàn)在我們來(lái)從幾個(gè)方面逐一溫習(xí)一下Spring的那些常用的值得關(guān)注的注解。

Spring核心注解

A. 首先來(lái)看一下各種stereotype:按分類定義了由Spring管理的各種組件,@Controller定義表現(xiàn)層組件,@Service定義業(yè)務(wù)邏輯層組件,@Repository定義數(shù)據(jù)訪問(wèn)層資源庫(kù)組件,@Component定義其它組件(比如訪問(wèn)外部服務(wù)的組件),之前也說(shuō)過(guò)了隨著這些注解功能無(wú)區(qū)別,但是對(duì)組件進(jìn)行合適的分類意義重大,不僅僅增加可讀性而且方便我們通過(guò)AOP對(duì)不同類型的組件進(jìn)行更多自動(dòng)增強(qiáng)

B.再來(lái)看看IOC相關(guān)的一些注解:@Autowired自動(dòng)裝配不用多說(shuō)了;@Required用于在setter方法標(biāo)記屬性值需要由Spring進(jìn)行裝配,對(duì)于目前版本的Spring這個(gè)注解已經(jīng)廢棄,現(xiàn)在Spring更推薦使用構(gòu)造方法注入;@Qualifier用于通過(guò)給Bean定義修飾語(yǔ)來(lái)注入相應(yīng)的Bean,和@Autowired一起使用相當(dāng)于@Resource的效果,當(dāng)然還有一種常見用法是嵌入其它注解用于對(duì)Bean進(jìn)行區(qū)分,然后配合@Autowired一起使用,參見后面提到的Spring Cloud的@LoadBalanced注解;@Value用于注入屬性配置或SpEL表達(dá)式(前者是我們常見用法,后者可以從其它對(duì)象獲取值,功能更強(qiáng)大一點(diǎn));@Lookup可以實(shí)現(xiàn)方法注入,如果我們的類是單例的,但是又希望Spring注入的依賴的對(duì)象是Prototype生命周期(每次new一個(gè)出來(lái))的,這個(gè)時(shí)候可以通過(guò)此注解進(jìn)行方法注入

C. 然后來(lái)看一下有關(guān)事務(wù)的幾個(gè)注解:@EnableTransactionManagement用于開啟事務(wù)管理,使用Spring Boot如果引入Spring Data的話不需要手動(dòng)開啟(不過(guò)建議大家在使用事務(wù)的時(shí)候還是通過(guò)日志來(lái)驗(yàn)證事務(wù)管理是否生效);@Transactional大家都知道用于開啟事務(wù)以及設(shè)置傳播性、隔離性、回滾條件等;@TransactionalEventListener用于配置事務(wù)的回調(diào)方法,可以在事務(wù)提交前、提交后、完成后以及回滾后幾個(gè)階段接受回調(diào)事件。

D. @Order注解可以設(shè)置Spring管理對(duì)象的加載順序,在之前介紹AOP的文章中我們看到有的時(shí)候我們必須通過(guò)設(shè)置合理的@Order來(lái)合理安排切面的切入順序避免一些問(wèn)題,還有在一些業(yè)務(wù)場(chǎng)景中,我們往往會(huì)去定義一組類似于Filter的@Component,然后會(huì)從容器獲得一組Bean,這個(gè)時(shí)候業(yè)務(wù)組件的運(yùn)行順序往往會(huì)比較重要,也可以通過(guò)這個(gè)方式進(jìn)行排序

E. @AliasFor注解可以設(shè)置一組注解屬性相互作為別名,對(duì)于有歧義的時(shí)候會(huì)使代碼更清晰,此外還有一個(gè)用途是創(chuàng)建復(fù)合注解,Spring MVC的@GetMapping注解就是基于@RequestMapping這個(gè)注解創(chuàng)建的復(fù)合注解,我們可以很方便得通過(guò)這種方式來(lái)實(shí)現(xiàn)注解的繼承

Spring上下文注解

A. 首先來(lái)看一下配置相關(guān)的一些注解:@Configuration用于標(biāo)注配置類,啟用Java配置方式的Bean配置;@Bean用于配置一個(gè)Bean;@ComponentScan@ComponentScans用于配置一組@ComponentScan,Java 8可以直接使用重復(fù)注解特性配置多個(gè)@ComponentScan)用于掃描包方式配置Bean;@PropertySource以及 @PropertySources用于導(dǎo)入配置文件;@Conditional用于設(shè)置關(guān)聯(lián)的條件類,在合適的時(shí)候啟用Bean的配置(Spring Boot自動(dòng)配置根基);@Import用于導(dǎo)入其它配置類; @ImportResource用于導(dǎo)入非Java配置方式的XML配置;@Profile用于指定在合適的Profile下啟用配置;@Lazy用于告知容器延遲到使用的時(shí)候?qū)嵗疊ean(默認(rèn)情況下容器啟動(dòng)的時(shí)候?qū)嵗疊ean來(lái)檢查所有的問(wèn)題);@Description用于給Bean設(shè)置描述;@Scope用于設(shè)置Bean的生命周期;@Primary用于在定義了多個(gè)Bean的時(shí)候指定首選的Bean

B. 其它一些注解包括:@EventListener用于設(shè)置回調(diào)方法監(jiān)聽Spring制定的以及自定義的各種事件;@EnableAspectJAutoProxy用于開啟支持AspectJ的 @Aspect切面配置支持,使用Spring Boot引入了AOP啟動(dòng)器的話不需要顯式開啟

Spring Web注解

Spring MVC的各種注解對(duì)應(yīng)了Spring MVC各方面的功能,下面我們來(lái)了解一下:

A. 首先是三個(gè)定義了Bean特殊生命周期的復(fù)合注解:@RequestScope、@SessionScope@ApplicationScope。在Web應(yīng)用中,我們可能需要Bean跟隨請(qǐng)求、會(huì)話和應(yīng)用程序的聲明周期來(lái)進(jìn)行創(chuàng)建,這個(gè)時(shí)候可以直接使用這三個(gè)快捷的復(fù)合注解

B. 接下去可以看到各種 @XXXMapping的注解,分別用于配置HandlerMethod匹配到不同的Http Method,當(dāng)然不使用這些快捷的注解也是可以的,直接使用@RequestMapping然后手動(dòng)設(shè)置method

C. @ResponseStatus可以用到方法上也可以用到異常上,前者會(huì)直接使請(qǐng)求得到指定的響應(yīng)代碼或原因(可以配合@ExceptionHandler使用),后者可以實(shí)現(xiàn)遇到指定異常的時(shí)候給出指定的響應(yīng)代碼或原因,@ResponseBody我們實(shí)現(xiàn)Restful接口的時(shí)候(@RestController)最常用了,把返回內(nèi)容(序列化后)輸出到請(qǐng)求體

D. Spring MVC給了我們各種注解方便我們從HTTP請(qǐng)求各種地方獲取參數(shù),@RequestBody從請(qǐng)求體(處理復(fù)雜數(shù)據(jù),比如JSON),@RequestHeader從請(qǐng)求頭,@CookieValue從cookie中,@SessionAttribute從會(huì)話中,@RequestAttribute從請(qǐng)求的Attribute中(比如過(guò)濾器和攔截器手動(dòng)設(shè)置的一些臨時(shí)數(shù)據(jù)),@RequestParam從請(qǐng)求參數(shù)(處理簡(jiǎn)單數(shù)據(jù),鍵值對(duì)),@PathVariable從路徑片段,@MatrixAttribute矩陣變量允許我們采用特殊的規(guī)則在URL路徑后加參數(shù)(分號(hào)區(qū)分不同參數(shù),逗號(hào)為參數(shù)增加多個(gè)值)

E. @ControllerAdvice是一個(gè)重要注解,允許我們?cè)诩械牡胤脚渲每刂破鳎ㄓ蠤RequestMapping的方法)相關(guān)的增強(qiáng)(@RestControllerAdvice也是差不多的,只是相當(dāng)于為@ExceptionHandler加上了@ResponseBody)。那么可以應(yīng)用哪些增強(qiáng)呢?首先是可以用 @ExceptionHandler進(jìn)行統(tǒng)一的全局異常處理;第二是 @InitBinder用來(lái)設(shè)置WebDataBinder,WebDataBinder用來(lái)自動(dòng)綁定前臺(tái)請(qǐng)求參數(shù)到Model中;第三是 @ModelAttribute讓全局的@RequestMapping都能獲得在此處設(shè)置的鍵值對(duì)。當(dāng)然,這里說(shuō)的@InitBinder和@ExceptionHandler也可以不定義在@ControllerAdvice內(nèi)部(作為全局開啟),定義在Controller內(nèi)部應(yīng)用到某個(gè)Controller也是可以的

F. 其它還有一些注解比如:@CrossOrigin可以用到Controller或Method上(需要配合@RequestMapping)設(shè)置細(xì)粒度的跨域行為

在之前的文章中我們也提到,對(duì)于Spring MVC,定義自己的注解應(yīng)用到參數(shù)、方法、控制器上,配合HandlerMethodArgumentResolver、XXAdvise、以及Interceptor實(shí)現(xiàn)具體的功能來(lái)使用太太常見了,幾乎所有的非業(yè)務(wù)橫切關(guān)注點(diǎn),我們都不應(yīng)該在方法實(shí)現(xiàn)中重復(fù)任何一行代碼。

Spring Boot注解

A. 來(lái)看一下上下文相關(guān)的注解:@ConfigurationProperties很常用(配合 @EnableConfigurationProperties注解來(lái)設(shè)置需要啟用的配置類),用來(lái)自定義配置類和配置文件進(jìn)行關(guān)聯(lián);@DeprecatedConfigurationProperty用于標(biāo)記廢棄的配置以及設(shè)置替代配置和告知廢棄原因;@ConfigurationPropertiesBinding用于指定自定義的轉(zhuǎn)換器用于配置解析的時(shí)的類型轉(zhuǎn)換; @NestedConfigurationProperty用于關(guān)聯(lián)外部的類型作為嵌套配置類

B. 再看看自動(dòng)配置相關(guān)的注解,自動(dòng)配置是Spring Boot最重要的特性,在之前的系列文章中我有提到一個(gè)觀點(diǎn),IOC是好事情,但是把組件內(nèi)部的一些默認(rèn)配置以及組件和組件的組裝交給外部用戶來(lái)配置其實(shí)是不合理的,組件應(yīng)當(dāng)可以自動(dòng)進(jìn)行自我配置實(shí)現(xiàn)開箱急用,只有需要自定義組件的時(shí)候才要求外部來(lái)進(jìn)行個(gè)性化配置:@EnableAutoConfiguration注解可以啟用自動(dòng)配置,Spring Boot應(yīng)用程序一般我們會(huì)直接使用復(fù)合注解@SpringBootApplication;@AutoConfigureOrder(值越小優(yōu)先級(jí)越高)、@AutoConfigureAfter@AutoConfigureBefore用于設(shè)置自動(dòng)配置類加載順序,以及精確控制加載依賴關(guān)系,有的時(shí)候我們的自動(dòng)配置需要相互依賴或者會(huì)相互干擾,需要手動(dòng)調(diào)節(jié)

C. 最后來(lái)看一下十幾種配置條件,用好這些注解是實(shí)現(xiàn)完善的自動(dòng)配置的關(guān)鍵:@ConditionalOnBean用于僅當(dāng)容器中已經(jīng)包含指定的Bean類型或名稱時(shí)才匹配條件;@ConditionalOnClass僅當(dāng)classpath上存在指定類時(shí)條件匹配;@ConditionalOnCloudPlatform僅當(dāng)指定的云平臺(tái)處于活動(dòng)狀態(tài)時(shí)條件匹配;@ConditionalOnExpression依賴于SpEL表達(dá)式的值的條件元素的配置注解;@ConditionalOnJava基于應(yīng)用運(yùn)行的JVM版本的條件匹配;@ConditionalOnJndi基于JNDI可用和可以查找指定位置的條件匹配;@ConditionalOnMissingBean僅當(dāng)容器中不包含指定的Bean類型或名稱時(shí)條件匹配;@ConditionalOnMissingClass僅當(dāng)classpath上不存在指定類時(shí)條件匹配;@ConditionalOnNotWebApplication 僅當(dāng)不是WebApplicationContext(非Web項(xiàng)目)時(shí)條件匹配,對(duì)應(yīng) @ConditionalOnWebApplication;@ConditionalOnProperty是檢查指定的屬性是否具有指定的值;@ConditionalOnResource表示僅當(dāng) classpath 上存在指定資源時(shí)條件匹配;@ConditionalOnSingleCandidate僅當(dāng)容器中包含指定的Bean類并且可以判斷只有單個(gè)候選者時(shí)條件匹配。其實(shí)所有這些實(shí)現(xiàn)原理都是擴(kuò)展SpringBootCondition抽象類(實(shí)現(xiàn)之前提到的Condition接口),我們完全可以實(shí)現(xiàn)自己的條件注解(配合 @Conditional注解關(guān)聯(lián)到自己實(shí)現(xiàn)的SpringBootCondition)

Spring Cloud注解

在介紹本系列文章的第一篇中我們就提到了,Spring Cloud整齊劃一通過(guò)各種EnableXXX注解開啟某個(gè)功能,這里就不對(duì)這些注解進(jìn)行說(shuō)明了,使用Spring Boot組件的功能非常簡(jiǎn)單,基本就是引POM+EnableXXX+設(shè)置配置文件三部曲。

A. 首先是 Netflix包下的一些注解,各種EnableXXX就不說(shuō)了,參考前一篇文章,之前沒(méi)介紹過(guò) @RibbonClient,這個(gè)注解用來(lái)為負(fù)載均衡客戶端做一些自定義的配置,可以進(jìn)一步配置或自定義從哪里獲取服務(wù)端列表、負(fù)載均衡策略、Ping也就是服務(wù)鑒活策略等等

B. client包下的 @SpringCloudApplication之前文章中我們也沒(méi)有使用到,這是一個(gè)復(fù)合注解就是 @SpringBootApplication+ @EnableDiscoveryClient+ @EnableCircuitBreaker,Spring Cloud那堆東西很多,還是自己親手定義一個(gè)一個(gè)功能的注解來(lái)的踏實(shí); @LoadBalanced注解用于和RestTemplate配合使用構(gòu)成一個(gè)負(fù)載均衡的Http客戶端,實(shí)現(xiàn)原理上其實(shí)這個(gè)注解是一個(gè)@Qualifier注解,Spring會(huì)為所有@LoadBalanced的RestTemplate加入一個(gè)LoadBalancerInterceptor(實(shí)現(xiàn)ClientHttpRequestInterceptor)實(shí)現(xiàn)負(fù)載均衡

C. sleuth包下面的注解和鏈路跟蹤相關(guān),比較常用的是通過(guò) @SpanName手動(dòng)設(shè)置span的名稱,其它注解對(duì)于業(yè)務(wù)開發(fā)并不常用

總結(jié)

好了,寫了本文我發(fā)現(xiàn)我看到@已經(jīng)Markdown的**就眼花,請(qǐng)點(diǎn)贊支持。本文我們通過(guò)代碼打印出了大部分Spring相關(guān)的注解,你也可以通過(guò)這個(gè)方式熟悉其它框架的注解(畢竟注解是框架賦予我們各種便捷功能的一個(gè)重要入口,對(duì)注解了解個(gè)八九成也往往可以對(duì)框架賦予我們的豐富功能了解六七成)。然后我們梳理了一下Spring相關(guān)的各種注解,其中主要需要關(guān)注的是幾方面:

  1. 元注解,也就是注解的注解

  2. Spring容器相關(guān)的一些注解,包括@Qualifier、@AliasFor、@Order等看似不重要但其實(shí)很重要的注解

  3. Spring Java配置相關(guān)的一些注解,包括條件注解

  4. Spring Boot自動(dòng)配置相關(guān)的一些注解

  5. 很多注解可以同時(shí)應(yīng)用到類型、方法、參數(shù)上,有的時(shí)候應(yīng)用到不同的地方作用會(huì)略微不一樣,這個(gè)需要重點(diǎn)關(guān)注

我們知道注解其實(shí)只是一個(gè)標(biāo)識(shí),注解如何起作用背后的實(shí)現(xiàn)原理還是比較多樣的,你可以進(jìn)一步結(jié)合本文介紹的Spring的各種注解探尋一下背后實(shí)現(xiàn)的原理。

寫在最后:小編為大家準(zhǔn)備了一些適合于1-5年以上開發(fā)經(jīng)驗(yàn)的java程序員面試涉及到的絕大部分面試題及答案做成了文檔和學(xué)習(xí)筆記文件以及架構(gòu)視頻資料免費(fèi)分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并發(fā)等架構(gòu)技術(shù)資料),希望可以幫助到大家。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
spring 注解模式 詳解
Spring3 MVC詳解二
如何自定義一個(gè)starter,你學(xué)廢了么?
《Spring3.X企業(yè)應(yīng)用開發(fā)實(shí)戰(zhàn)》學(xué)習(xí)筆記
SpringBoot的幕后推手...
springboot注解詳解(三)容器配置注解與Spring Boot注解
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服