【framework】spring-註解(annotation)

weixin_33858249發表於2017-11-23

近來發現把寫部落格當成任務了。呵呵,調整下了下心態:我在這裡寫,只是希望你看到,能有所幫助。

spring註解的發展史

在spring2.5的官方指導裡指出,spring從2.0開始引入了一些用於配置的annotation, 包括 @Transactional, @Required and @PersistenceContext/@PersistenceUnit.

然而我在一篇文章裡,看到spring註解從1.2開始便有了,於是我不得不回頭去查閱了下spring相關文件。得出如下結論:

1. spring1.0: 從1.0開始就在對後設資料問題出謀劃策,沒有正式引入註解。但有了SOURCE級別的後設資料支援

2. spring1.2: 在1.2的時候是java1.5的釋出,並且面對要相容1.3,1.4版本的問題,但已經有了基於java5.0的註解如: @ManagedResource,基本無關注。 aspectJ 在該版本中仍在建設過程中,還停留在aspect。

3. spring2.0 :有了比較多的註解,包括AspectJ已經採用了註解方法,並且支援xml配置

4. spring2.5: 引入了用於配置的完整的Annotation集合: @Autowired,以及對JSR-250註解@Resource, @PostConstruct and @PreDestroy的支援

5. spring3.0: 註解已經非常的豐富,spring的 JavaConfig專案已經加入到spring框架中,這意味著將直接支援如@Configuration,@Bean,@Value等標籤

6. spring3.1: 對@Configuration有所增強,充實。 

認識註解:

我相信大家接觸註解(annotation),最早應該是@Override,@Deprecated,@Suppress Warnings,就算接觸不多,也沒關係,我這裡儘量系統的說一遍。

1. 註解:也被叫做 後設資料(其實我覺得更是後設資料的一種表現形式),為程式碼新增資訊提供了一種形式化的方法,在稍後的某個時候用到這些資料

2. 後設資料: 用於描述資料的資料(MetaDate),翻譯成資訊的資訊會跟更好理解,舉例來說:我這邊文章就是一些資料,或者資訊,而對這個文章的標題,時間,關鍵字,都可以稱為後設資料

3. 註解是後設資料與原始碼結合在一起,但不儲存在外部文件(如xml)的趨勢下催生的

陰暗的說,其實你知道上面這些也沒大用,反正能寫能用就成,下面介紹註解的格式 

註解的格式

注意: 註解本身不做任何事

註解可以與其他任何修飾符共同作用於方法,例如public,static或者void。從語法角度看,註解的使用方式與修飾符使用幾乎一模一樣。

為何說幾乎,舉例:

有方法:

  public void create(int i){}
和 註解
  @Test, @Test1

可以如下寫法:

1.


  1. @Test  
  2. public void create(int i){} 

2.


  1. public @Test void create(int i){}  

  1. @Test public void create(int i){}   
  2. //注意不能放在void的後面 

3.


  1. public void create(@Test int i){}  

4.


  1. @Test@Test1  
  2. public void create(int i){}  
  3. //註解以@分隔,與空白符包括行(row) 無關 

 java中自定義一個註解和應用:

只舉一個簡單例子,算是入門。但對你理解spring註解將會是個不錯的過渡,至少你能感覺到,註解原來這麼簡單。

例子:


  1. import java.lang.annotation.*;   
  2. @Target(ElementType.METHOD)//註解只能用於方法   
  3. @Retention(RetentionPolicy.RUNTIME)//註解在執行期也保留,可以通過反射讀取註解資訊   
  4. public @interface Scholar {   
  5.     public int id();   
  6.     public String descrition() default "no description";   
  7. }  
  8.  

建立一個類TestScholar 來應用@Scholar

程式碼:


  1. //@Scholar(id=1)//Scholar只能用於方法
  2. public class TestScholar {   
  3.     @Scholar(id=1)   
  4.     public void test() {};   

  效果圖:
image
通過上面的例子,對註解算是有些認識。注意:
1. @Target如果你是第一次接觸,不要急,下面有講解
2. 你需要注意 註解的方式很像介面欄位定義需要加小括號
3. 註解可以有預設,如果預設(default),則可以不賦值

元註解

記得後設資料的解釋嗎?是的,元註解專職負責註解其他註解 

元註解

引數

說明

@Target

  表示註解可用於什麼地方
  CONSTRUCTOR 構造器的宣告
  FIELD 域宣告(包括enum例項)
  LOCAL_VARIABLE 區域性變數宣告
  METHOD 方法宣告
  PACKAGE 包宣告
  PARAMETER 引數宣告
  TYPE 類,介面(包括註解)或者enum宣告

@Retention

 

表示需要什麼級別儲存該註解資訊

  SOURCE 註解將被編譯器丟棄
  CLASS 註解在class檔案中可用,會被VM丟棄
  RUNTIME VM在執行期被保留,可以通過反射機制讀取註解

@Documented

 

將此註解包含在Javadoc中

@Inherited

 

允許子類整合父類中的註解

 註解型別

所有基本型別(int,float,boolean等)
String

Class
enum
Annotation
以上型別的陣列

 

讀取註解的內容:

通過反射機制,都會有getAnnotation()方法

如方法(Method)的: 


  1. for(Method m : of.getDeclaredMethods())  
  2. Scholar scholar = m.getAnnotation(Scholar.class)  

如果是初學,可能要去專門學習下,呵呵,這裡只是為了給spring做個入門。


spring2.5 註解

spring2.5算是一個里程碑的版本,而註解2個比較大的改革便是:
1. Annotation驅動的bean配置
2. 對Spring MVC的支援

分別講解一下:

1.Annotation驅動的bean配置

1.1 基於註解(Annotation-based)的配置

要使註解可用,您必須使用 Java 5 (Tiger)或更新的版本,以使得可以訪問原始碼層次的註解。這些註解可以被註冊為獨立 bean 的定義,但它們也可以被隱式地註冊,通過基於 XML 的配置方式,如下例(請注意包含 'context' 名稱空間):


  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:context="http://www.springframework.org/schema/context" 
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans   
  6.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  7.            http://www.springframework.org/schema/context  
  8.            http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 
  9. <context:annotation-config/>     
  10.   <!--注意:xmlns:context="http://www.springframework.org/schema/context" -->        
  11.   <!--(隱式註冊 post-processors 包括了
  12. AutowiredAnnotationBeanPostProcessor
  13. CommonAnnotationBeanPostProcessor
  14. PersistenceAnnotationBeanPostProcessor也包括了前面提到的 RequiredAnnotationBeanPostProcessor。) -->
  15. </beans> 

1.2 @Autowired

引用些官方例子:

1)@Autowired 註解可以用於“傳統的”setter 方法,如下例:


  1. public class SimpleMovieLister {  
  2.     private MovieFinder movieFinder;  
  3.     @Autowired  
  4.     public void setMovieFinder(MovieFinder movieFinder) {  
  5.         this.movieFinder = movieFinder;  
  6.     }  
  7.     // ...  

2)這個註解也可以用於以屬性為引數/多個引數的方法


  1. public class MovieRecommender {  
  2.     private MovieCatalog movieCatalog;  
  3.     private CustomerPreferenceDao customerPreferenceDao;  
  4.  
  5.     @Autowired  
  6.     public void prepare(MovieCatalog movieCatalog,  
  7.             CustomerPreferenceDao customerPreferenceDao) {  
  8.         this.movieCatalog = movieCatalog;  
  9.         this.customerPreferenceDao = customerPreferenceDao;  
  10.     } 
  11. // ...  

3@Autowired註解甚至可以用於構造器與欄位:


  1. public class MovieRecommender {  
  2.     @Autowired  
  3.     private MovieCatalog movieCatalog;  
  4.     private CustomerPreferenceDao customerPreferenceDao;  
  5.     @Autowired  
  6.     public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {  
  7.         this.customerPreferenceDao = customerPreferenceDao;  
  8.     } 
  9. // ...  

4)也可以一種提供來自ApplicationContext的特殊型別的所有 beans,註解欄位或者方法,例如:


  1. public class MovieRecommender {  
  2.     @Autowired  
  3.     private MovieCatalog[] movieCatalogs;   
  4.     // ...  

5)這同樣適用於集合型別:


  1. public class MovieRecommender {  
  2.     private Set<MovieCatalog> movieCatalogs;  
  3.  
  4.     @Autowired  
  5.     public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {  
  6.         this.movieCatalogs = movieCatalogs;  
  7.     }   
  8.     // ...  
  9. }  

注意:在預設情況下,當出現0個候選的 beans時自動連線將失敗;預設行為把連線方法,構造器,欄位假設為 required 的依賴。這樣的行為如下所示:


  1. public class SimpleMovieLister {  
  2.     private MovieFinder movieFinder;  
  3.  
  4.     @Autowired(required = false)  
  5.     public void setMovieFinder(MovieFinder movieFinder) {  
  6.         this.movieFinder = movieFinder;  
  7.     }   
  8.     // ...  
  9. }  

1.3 基於註解的微調

1)有多個例項,需要篩選出一個,可以通過Qualifier註解


  1. public class MovieRecommender {  
  2.     @Autowired  
  3.     @Qualifier("mainCatalog")  
  4.     private MovieCatalog movieCatalog;   
  5.     // ...  

2)@Qualifier註解也能夠被指定為構造器的引數或者方法的引數:


  1. public class MovieRecommender {  
  2.     private MovieCatalog movieCatalog;  
  3.     private CustomerPreferenceDao customerPreferenceDao;  
  4.  
  5.     @Autowired  
  6.     public void prepare(@Qualifier("mainCatalog") MovieCatalog movieCatalog,  
  7.             CustomerPreferenceDao customerPreferenceDao) {  
  8.         this.movieCatalog = movieCatalog;  
  9.         this.customerPreferenceDao = customerPreferenceDao;  
  10.     }   
  11.     // ...  

2.對Spring MVC的支援

Spring 2.5 為MVC 控制器引入了一種基於Annotation(註解)的程式設計模型, 使用@RequestMapping, @RequestParam, @ModelAttribute等等註解。 

1.要實現控制器@Controller自動探測

加入配置


  1. <!--package是要掃描的包-->
  2. <context:component-scan base-package="org.springframework.samples.petclinic.web"/> 

2.一個例項


  1. @Controller  
  2. @RequestMapping("/editPet.do")  
  3. @SessionAttributes("pet")  
  4. public class EditPetForm {  
  5.     private final Clinic clinic;  
  6.  
  7.     @Autowired  
  8.     public EditPetForm(Clinic clinic) {  
  9.         this.clinic = clinic;  
  10.     }  
  11.  
  12.     @ModelAttribute("types")  
  13.     public Collection<PetType> populatePetTypes() {  
  14.         return this.clinic.getPetTypes();  
  15.     }  
  16.  
  17.     @RequestMapping(method = RequestMethod.GET)  
  18.     public String setupForm(@RequestParam("petId") int petId, ModelMap model) {  
  19.         Pet pet = this.clinic.loadPet(petId);  
  20.         model.addAttribute("pet", pet);  
  21.         return "petForm";  
  22.     }  
  23.  
  24.     @RequestMapping(method = RequestMethod.POST)  
  25.     public String processSubmit(@ModelAttribute("pet") Pet pet,  
  26.             BindingResult result, SessionStatus status) {  
  27.         new PetValidator().validate(pet, result);  
  28.         if (result.hasErrors()) {  
  29.             return "petForm";  
  30.         } else {  
  31.             this.clinic.storePet(pet);  
  32.             status.setComplete();  
  33.             return "redirect:owner.do?ownerId=" + pet.getOwner().getId();  
  34.         }  
  35.     }  

spring2.5 對註解的2個主要關注點已經闡述,但是隨著註解的大量應用,spring可能融入一些其他的框架,如AspectJ ,都會有自己的註解,需要大家瞭解並且注意,但是他並不是與spring-framework實際相關。

收尾

我想這些東西,很多人都應該寫過,這裡就不反覆闡述。我寫文章的目的,是為spring3新特徵和加強(包括註解)做鋪墊,有時間就寫寫。










本文轉自 wws5201985 51CTO部落格,原文連結:http://blog.51cto.com/yjplxq/976539,如需轉載請自行聯絡原作者

相關文章