- N +

springboot核心注解原理 java注解的實現原理

老鐵們,大家好,相信還有很多朋友對于springboot核心注解原理和java注解的實現原理的相關問題不太懂,沒關系,今天就由我來為大家分享分享springboot核心注解原理以及java注解的實現原理的問題,文章篇幅可能偏長,希望可以幫助到大家,下面一起來看看吧!

SpringBoot中,@Autowired和@Resource使用起來到底有什么區別

這個問題也有一段時間了,當初也就隨手一寫,直到最近還有網友在看,為了保證大家看的時候不會出現理解方面的問題,于2021-5-10編輯一次,希望能更加嚴謹一點,至少不會誤導大家。

首先,這個問題有點不準確,這2個注解是使用Spring框架過程中常用的注解,而SpringMVC和SpringBoot等框架都是基于Spring的進階框架,并沒有對這2個注解的使用進行修改或者調整,所以,只討論Spring框架如何處理這2個注解即可,而不是討論在SpringBoot中的使用區別。

【結論】在絕大部分情況下,使用這2個注解的任何一個都可以實現自動裝配,在使用方面是無感的。

如果要討論區別,基本上就是2點:

所屬不同:@Resource注解是javax包的;@Autowired是Spring聲明的;裝配機制不同:@Resource會優先byName來裝配,即使名稱不匹配,也會嘗試byType來裝配;@Autowired則是先查找匹配類型對象的數量,如果有且僅有1個,則直接裝配,如果為0個,則無法裝配,此時需要考慮該注解的required屬性,默認是true,就會因為“必須裝配卻沒有匹配類型的對象”而拋出異常,如果顯式的設置為false,則不裝配,保持被自動裝配的屬性為null值,如果匹配類型的對象超過1個,則會嘗試byName,如果成功,則裝配,如果失敗,則拋出異常。

如果一定要說還有其它區別,可以是:

作用范圍不同:@Resource用于對字段、Setter方法進行注解,@Autowired可用于構造方法、Setter方法和字段;當同一種類型的對象有多個時(例如聲明的類型是接口,在Spring容器中有2個或多個實現類的對象),需要指定名稱,@Resource可直接配置name屬性來指定bean-name,而@Autowired需要配合@Qualifer注解,由@Qualifer注解來指定bean-name,當用于字段時,直接在字段的聲明之前使用這2個注解,當用于Setter方法時,在方法的聲明之前使用@Autowired,在方法的參數之前使用@Qualifer;

另外,還有很多關于使用@Autowired的細節問題,例如“是不是不建議使用了”、“到底應該怎么用”等等,所以,接下來主要討論這些問題。

關于“是不是不建議使用了”,這種問題的主要原因應該是最近幾年IntelliJIDEA越來越流行了,而許多版本的IntelliJIDEA對@Autowired的預判是有問題的!也就是說:IntelliJIDEA會在編碼期實時預判是否存在可以裝配的對象,如果它認為沒有,就會報錯,事實上,它的判斷并不完全準確!

例如,嘗試在Service組件中裝配一個Mapper接口類型的字段時:

(截圖來自IntelliJIDEA2020.1.4)

以上報錯就是IntelliJIDEA預判錯誤導致的,如果使用的是Eclipse就不會有這樣的問題,解決方案可以是:

在UserMapper接口上添加@Repository注解;將以上代碼中的@Autowired配置為@Autowired(required=false),因為@Autowired默認是required=true,同時IntelliJIDEA認為沒有可裝配對象,所以報錯,顯式的配置為required=false之后,即使IntelliJIDEA認為沒有可裝配對象也不會報錯了;將以上代碼中的@Autowired改為@Resource。

再例如在使用SpringSecurity進行配置時也會有類似的問題,只不過這次它認為“存在多個匹配類型的對象”:

(截圖來自IntelliJIDEA2020.1.4)

解決以上報錯信息的方式可以是:

將聲明的UserDetailsService接口類型改為你的UserDetailsServiceImpl實現類類型,例如privateUserDetailsServerImplservice;即可;將以上代碼中的@Autowired改為@Resource。

由于許多類似問題都可以通過“將@Autowired改為@Resource”來解決,加上一些相關說法(詳見下文),且某些片面的斷章取義,導致網上還存在“使用@Resource取代@Autowired”、“以后不要再用@Autowired”的說法,而這些說法都是錯誤的,沒有任何官方(開發工具的IntelliJIDEA,或框架官方Spring)說過這樣的話!

首先,使用Spring實現自動裝配時,有3種方式:

通過構造方法注入;通過Setter注入(即與字段屬性匹配的set方法);通過字段注入;

基本示例參見下圖:

以上圖片來自Spring官方提供的資料,可以看到最后還附了個URL,是國外網友寫的一篇主題為《whyfieldinjectionisevil》的討論文章,有興趣且有一定英語閱讀能力的朋友可以自行上網查看全文,大意是“使用字段注入時可能導致NPE”!為什么會這樣呢?假設你有如下代碼:

如果你因為某種原因直接創建對象,即通過UserServiceservice=newUserService();來創建對象,其中的userRepository屬性肯定是沒有值的,后續使用這個service對象時,只要涉及調用userRepository就會出現NPE了!

既然UserService是一個組件,為什么還會直接創建對象呢?其實這也算是一個低概率的特殊情況,在彼此不太熟悉的協同工作中可能出現,例如你和我一起開發項目,我對你寫的那部分代碼不太了解……再就是測試使用時,也可能出現直接創建對象的情況……

如果將代碼改為下面這樣:

則剛才的問題就不存在了!因為現在的構造方法是需要參數的,你不給參數,就創建不了對象!如果能創建出對象,就肯定給了參數,則userRepository肯定有值,就不會出現NPE!當然,如果你一定要傳個null進去就沒辦法了,Nozuonodiewhyyoutry?

所以,使用構造方法傳遞參數是一種強制依賴的做法,可以保證不會出現NPE,但是,如果參數太多會不會很奇怪?真的有必要把代碼寫得這么滴水不漏嗎?這個就看你自己了!首先,是IntelliJIDEA并不建議你使用字段注入:

(截圖來自IntelliJIDEA2020.1.4)

而Spring的觀點,可參見下圖:

可以看到,Spring是無所謂的,反正都能用(Springdoesn'tcare,canuseeither),當然,也列舉了使用構造方法注入和使用Setter注入的區別(雖然我在前面都是寫的字段注入,在NPE問題上,字段注入和Setter注入是一樣的)。

既然Spring都無所謂了,我們為什么還要糾結注入方式呢?還是那句話,只要你能保證不出錯,怎么都行!可能95%以上的Java從業者不是在寫大廠的大型項目,合格的程序員也不會亂寫代碼,由Setter或字段注入導致NPE的概率本來就極低,不一定需要為了“保證極端情況下也不出錯”而刻意的把代碼調整為構造方法注入,只要注意規避這個問題即可!

另外,我在上面的代碼演示中,在構造方法上加了@Autowired注解,在這里解釋一下:

如果類中只存在默認構造方法(無論是你顯式的添加的,還是根本不寫,由編譯器添加的),則無需@Autowired注解,Spring會自動調用,當然,加了也不會出錯;如果類中只存在唯一的構造方法,Spring會自動調用,且會自動從Spring容器中找對象裝配為調用構造方法的參數,這種情況也是不需要添加@Autowired注解的,加了也不會出錯;如果類中存在多個構造方法,且都沒有添加@Autowired注解時,當存在無參數構造方法時,Spring會自動調用無參數構造方法,如果你想要Spring調用另外某一個構造方法,就在那個構造方法上添加@Autowired注解;如果類中存在多個構造方法,且超過1個構造方法上都添加了@Autowired注解……你別作,你不需要知道Spring怎么處理,你只要把@Autowired刪得只有1個了,就肯定沒問題!

所以,從道理上來說,應該推薦顯式的為某1個構造方法添加@Autowired注解,哪怕是不需要添加也能用,因為這樣會保證多構造方法的情況下代碼更加直觀,增加代碼的可讀性,但是,從實際工作出發,可能就變成了“有啥好加的?這點道理都不懂還上什么班?”……大家都懶得加了,所以,又不是什么很難懂的原理,加不加就自行把握吧。

最后,再總結一下使用原則:

@Autowired和@Resource在使用時可以不糾結它們的區別,使用它們的目的就是為了裝配對象,只要能裝得上,裝的是對的,無所謂使用哪個?一定要區分選取,先保證“在同一個項目中使用同一個”,不要一個類使用@Autowired,另一個類又使用@Resource,然后,我個人建議使用@Autowired,原因嘛,很簡單,你既然用Spring框架,就用它帶的注解唄;關于@Autowired的使用方式,不怕麻煩就都使用構造方法注入,且顯式的添加@Autowired,如果怕麻煩,只要不出錯,就隨意吧。

Spring官方也考慮到了網友關于@Resource或相關注解的問題,因為沒什么需要特別解釋的了,就直接貼圖好了,大家自行查閱,以下圖片仍是來自Spring官方資料:

最后,近期因為工作的關系看了不少Spring的官方資料,包括官方的Spring學習教程,有些感慨,給我的感覺,Spring對外提倡實用主義,極少和你講理論,源碼什么的更是少得可憐,這也和面向對象的思想保持一致,人家都幫你做好了,你好好用就行了,不必關心實現細節,希望大家也能這樣!現在IT行業真的被一些大廠帶節奏了,網上各種吸引眼球的XX源碼解析、XX底層原理、XX加載過程分析、XX算法、大廠案例、大廠面試題……很多時候真的想噴一句“你咋不從操作系統開始做軟件研發呢”……真的,絕大部分Java從業者一輩子都進不了大廠,也接觸不到超過20臺以上服務器才能扛得住的項目,除非是為了應付面試,你甚至不需要知道i++和++i的區別,如果只是自己寫代碼自己用,你也不需要知道private和public的區別……如果你只想開自己的私家車,不想修車也不想造車,除了吹牛,你都不需要知道發動機的型號……多掌握實用技術,多積累解決問題的經驗,原理什么的能不管就不要管,當熟練到一定程度后,再考慮要不要深入了解原理。

好了,就這么多,如果有錯別字,大家將就一下吧(可編輯次數有限),如果有覺得不對的地方,歡迎留言討論。

springbootmain方法啟動注解的區別

那要看你使用的是自動加載獲取spring上下文還是手動加載獲取spring上下文,如果是手動用編碼方式加載spring的xml配置文件,那就可以用main里面運行,要是使用服務器已啟動時自動加載spring配置文件,那就不能使用main方法了,呼呼

springboot定時任務沒到時間就執行

用SpringBoot創建定時任務非常簡單,目前主要有以下三種創建方式:

一、基于注解(@Scheduled)

二、基于接口(SchedulingConfigurer)前者相信大家都很熟悉,但是實際使用中我們往往想從數據庫中讀取指定時間來動態執行定時任務,這時候基于接口的定時任務就派上用場了。

三、基于注解設定多線程定時任務

一、靜態:基于注解

基于注解@Scheduled默認為單線程,開啟多個任務時,任務的執行時機會受上一個任務執行時間的影響。

1、創建定時器

使用SpringBoot基于注解來創建定時任務非常簡單,只需幾行代碼便可完成

springboot跳轉頁面的注解是哪個

在SpringBoot中,用于跳轉頁面的注解是`@RequestMapping`,其主要作用是將HTTP請求映射到控制器的處理方法,并可以指定返回的視圖名稱或視圖路徑。

但是在SpringBoot2.0之后,為了規范,Spring官方推薦使用更為明確的注解`@GetMapping`、`@PostMapping`等來替代`@RequestMapping`來標記請求的方法。所以,一般情況下我們會使用`@GetMapping`注解來進行頁面的跳轉。

spring boot使用shiro還是secuitry好

Shiro和SpringSecurity都是安全框架,簡單說是對訪問權限進行控制,他們都提供了認證、授權、加密、會話管理;這里要提一句,通常這種安全框架不會去幫助我們維護用戶/權限;這些需要我們自己去實現,然后通過相應的接口注入給安全框架。

那么SpringBoot項目的話,是使用Shiro還是SpringSecurity呢?還是先看看兩者有什么區別和各自的優缺點:

Shiro的配置和使用比較簡單,SpringSecurity上手復雜些;

Shiro依賴性低,理論上不需要任何框架和容器,可以獨立運行(但是最常用的環境還是JavaEE);SpringSecurity依賴Spring容器;

Shiro支持Web項目和非Web項目;在集群環境中,Shiro可以獨立于容器;

SpringSecurity基于Spring開發,項目若使用Spring(包括SpringBoot)作為基礎,配合SpringSecurity做權限更加方便;Shiro需要和Spring進行整合(不過這個復雜程度可以忽略);

SpringSecurity對Oauth、OpenID也有支持,Shiro則需要自己手動實現。

總結一下,SpringBoot使用Shiro還是SpringSecurity,我更傾向于Shiro。

一方面雖然Shiro需要和SpringBoot做整合,但是這個過程不復雜;

另外一方面Oauth、OpenID站點間統一登錄功能,會有更好的實現方案,很少在這個層級實現,所以SpringSecurity的這兩個功能可以不考慮。

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。

如何快速上手Spring boot

推薦以SpringBoot教程與SpringCloud教程的詳細開源項目“SpringBoot-Learning”此項目內容為SpringBoot教程程序樣例,對于SpringBoot的初學者來說非常有用,文末也列出了Spring相關開源項目,供大家交流學習。

1.SpringBoot-Learning部分樣例:

快速入門

chapter1:基本項目構建(可作為工程腳手架),引入web模塊,完成一個簡單的RESTfulAPI使用Intellij中的SpringInitializr來快速構建SpringBoot/Cloud工程

工程配置

chapter2-1-1:配置文件詳解:自定義屬性、隨機數、多環境配置等

Web開發

chapter3-1-1:構建一個較為復雜的RESTfulAPI以及單元測試chapter3-1-2:使用Thymeleaf模板引擎渲染web視圖chapter3-1-3:使用Freemarker模板引擎渲染web視圖chapter3-1-4:使用Velocity模板引擎渲染web視圖chapter3-1-5:使用Swagger2構建RESTfulAPIchapter3-1-6:統一異常處理

數據訪問、日志管理等等,項目地址:程序猿DD/SpringBoot-Learning-碼云Gitee.com

2.項目名稱:springboot實踐學習案例springboot-learning-example

項目結構:

a.『基礎-入門篇』

springboot-helloworld《SpringBoot之HelloWorld詳解》springboot-properties《SpringBoot之配置文件詳解》

b.『基礎-Web業務開發篇』

springboot-restful《Springboot實現Restful服務,基于HTTP/JSON傳輸》《SpringBoot之RESRfulAPI權限控制》springboot-freemarker《SpringBoot集成FreeMarker詳解案例》springboot-validation-over-json《SpringBootHTTPoverJSON的錯誤碼異常處理》

c.『基礎–數據存儲篇』

springboot-mybatis《Springboot整合Mybatis的完整Web案例》springboot-mybatis-annotation《SpringBoot整合MybatisAnnotation注解的完整Web案例》springboot-mybatis-mutil-datasource《SpringBoot整合Mybatis實現Druid多數據源詳解》

d.『基礎–數據緩存篇』

springboot-mybatis-redis《SpringBoot整合Redis實現緩存操作》springboot-mybatis-redis-annotation《SpringBoot注解實現整合Redis作為緩存》

e.『其他篇』

springboot-elasticsearch《SpringBoot整合Elasticsearch,實現functionscorequery權重分查詢》springboot-dubbo-serverspringboot-dubbo-clientDubbo服務提供者工程和Dubbo服務消費者工程《Springboot整合Dubbo/ZooKeeper詳解SOA案例》《SpringBoot中如何使用DubboActivate擴展點》

SpringDataES篇

spring-data-elasticsearch-crud《SpringDataElasticsearch-基本案例》spring-data-elasticsearch-queryspring-data-elasticsearch-實戰案例詳解

項目地址:泥沙磚瓦漿木匠/springboot-learning-example-碼云Gitee.com

Spring相關項目推薦:

1.項目名稱:基于Spring+SpringMVC+Mybatis分布式敏捷開發系統架構

項目內容:基于Spring+SpringMVC+Mybatis分布式敏捷開發系統架構,提供整套公共微服務服務模塊:集中權限管理(單點登錄)、內容管理、支付中心、用戶管理(支持第三方登錄)、微信平臺、存儲系統、配置中心、日志分析、任務和通知等,支持服務治理、監控和追蹤,努力為中小型企業打造全方位J2EE企業級開發解決方案。

項目地址:shuzheng/zheng-碼云Gitee.com

2.項目名稱:模塊化開發系統ybg-spring-fast

項目簡介:以SpringBoot為中心,模塊化開發系統,用戶可以隨意刪減除權限框架外任意的系統模塊。復用,組裝性強主要應用技術:springSecurity+Ehcache+quartz+swagger2+Mysql5.6+springjdbc+druid+springsocial+springsession+layerui+vue.js等。

項目地址:YYDeament/ybg-spring-fast-碼云Gitee.com

3.項目名稱:JAVA分布式快速開發平臺iBase4J

項目內容:JAVA分布式快速開發平臺:SpringBoot,SpringMVC,Mybatis,mybatis-plus,motan/dubbo分布式,Redis緩存,Shiro權限管理,Spring-Session單點登錄,Quartz分布式集群調度,Restful服務,QQ/微信登錄,Apptoken登錄,微信/支付寶支付;日期轉換、數據類型轉換、序列化、漢字轉拼音、身份證號碼驗證、數字轉人民幣、發送短信、發送郵件、加密解密、圖片處理、excel導入導出、FTP/SFTP/fastDFS上傳下載、二維碼、XML讀寫、高精度計算、系統配置工具類等等。

項目地址:iBase4J/iBase4J-碼云Gitee.com

4.項目名稱:JavaEE(J2EE)快速開發框架ThinkGem

項目內容:JavaEE(J2EE)快速開發框架,基于經典技術組合(SpringMVC、ApacheShiro、MyBatis、BootstrapUI),包括核心模塊如:組織機構、角色用戶、權限授權、數據權限、內容管理、工作流等。雖說很長時間沒有大的更新了,但它的架構精良易于擴展深受大家喜愛,依然是中小企業的首選,它的功能設計、底層架構也非常具有參考意義、是學習入門的首選。關注我ThinkGem開源中國博客了解4.0最新動態。

項目地址:ThinkGem/JeeSite-碼云Gitee.com

5.項目名稱:Java快速開發平臺MCMS

項目內容:完整開源,Java快速開發平臺。基于Spring、SpringMVC、Mybatis架構,MStore提供更多好用的插件與模板(文章、商城、微信、論壇、會員、評論、支付、積分、工作流、任務調度等,同時提供上百套免費模板任意選擇),價值源自分享!銘飛系統不僅一套簡單好用的開源系統、更是一整套優質的開源生態內容體系。

項目地址:銘飛/MCMS-Gitee

6.項目名稱:基于SpringCloud微服務化開發平臺AG-Admin

項目內容:AG-Admin是國內首個基于SpringCloud微服務化開發平臺,具有統一授權、認證后臺管理系統,其中包含具備用戶管理、資源權限管理、網關API管理等多個模塊,支持多業務系統并行開發,可以作為后端服務的開發腳手架。代碼簡潔,架構清晰,適合學習和直接項目中使用。核心技術采用Eureka、Fegin、Ribbon、Zuul、Hystrix、JWTToken、Mybatis等主要框架和中間件,前端采用vue-element-admin組件。

項目地址:老A/AG-Admin-碼云Gitee.com

7.項目名稱:輕量級的SpringBoot快速開發平臺renren-fast

項目簡介:renren-fast是一個輕量級的SpringBoot快速開發平臺,其設計目標是開發迅速、學習簡單、輕量級、易擴展;使用SpringBoot、Shiro、MyBatis、Redis、Bootstrap、Vue2.x等框架,包含:管理員列表、角色管理、菜單管理、定時任務、參數管理、代碼生成器、日志管理、云存儲、API模塊(APP接口開發利器)、前后端分離等。

關于springboot核心注解原理,java注解的實現原理的介紹到此結束,希望對大家有所幫助。

返回列表
上一篇:
下一篇: