前言
這段時間bug有點多,白天的時間幾乎都用在改bug了,近一個月都很少看書了,得趕緊改完bug看書。在spring源碼分析結(jié)束之后,我們也已經(jīng)完成了循環(huán)依賴的解決方案以及設計模式,那么接下來我們分析下Spring中常用的注解。
這里先說明下注解類型。
Annotition的類型使用關(guān)鍵字 @interface 而不是interface。它繼承了java.lang.annotition.Annotition接口,并非申明了一個interface。
Annotation類型、方法定義是獨特的、受限制的:
Annotation類型的方法必須申明為無參數(shù)、無異常拋出的。這些方法定義了 Annotation的成員:方法名為成員名,而方法返回值為成員的類型。
特別的,如果方法名為 value(), 則在注解的地方需要設置屬性值時可以直接寫入值,如:@Target({ElemenetType.TYPE}) 而不必寫為 @Target(value={ElemenetType.TYPE})
方法返回值必須為primitive類型、Class類型、枚舉類型、Annotation類型或者由前面類型之一作為元素的一位數(shù)組。
方法的后面可以使用default關(guān)鍵字加一個默認數(shù)值來申明成員的默認值,null不能作為成員的默認值,這與我們在非Annotation類型中定義方法有很大不同。
Annotation類型和他的方法不能使用Annotation類型的參數(shù),成員不能是generic。只有返回值類型是Class的方法可以在Annotation類型中使用generic,因為此方法能夠用類轉(zhuǎn)換將各種類型轉(zhuǎn)換為Class。
Annotation類型又與接口有著近似之處:它可以定義常量、靜態(tài)成員類型(比如枚舉類型定義);Annotation類型也可以如接口一般被實現(xiàn)或者繼承。
1、元注解
元注解的作用就是負責注解其他注解。Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其它annotation類型作說明 。
- 1.@Target,
- 2.@Retention,
- 3.@Documented,
- 4.@Inherited
這些可以通過Spirngboot的注解@SpringBootApplication
了解到。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
1.1、@Target
用于設定注解使用范圍
【詳細參考】@Target注解
Target通過ElementType來指定注解可使用范圍的枚舉集合。
- ElementType.TYPE: 接口、類、枚舉、注解
- ElementType.FIELD: 字段、枚舉的常量
- ElementType.METHOD: 方法
- ElementType.PARAMETER: 方法參數(shù)
- ElementType.CONSTRUCTOR: 構(gòu)造函數(shù)
- ElementType.LOCAL_VARIABLE: 局部變量
- ElementType.ANNOTATION_TYPE: 注解
- ElementType.PACKAGE: 包
1.2、@Retention
定義注解的保留策略。
【詳細參考】@Retention
通過RetentionPolicy來指定注解的枚舉集合。
- RetentionPolicy.SOURCE :注解僅存在于源碼中,在class字節(jié)碼文件中不包含
- RetentionPolicy.CLASS:默認的保留策略,注解會在class字節(jié)碼文件中存在,但運行時無法獲得
- RetentionPolicy.RUNTIME:注解會在class字節(jié)碼文件中存在,在運行時可以通過反射獲取到
1.3、@Documented
用于描述其它類型的annotation應該被作為被標注的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化。Documented是一個標記注解,沒有成員。
1.4、@Inherited
說明子類可以繼承父類中的該注解
- 被@Inherited注解的注解只有在class上使用才會有“自動繼承的特性”
- “自動繼承的特性”是指如果在子類上搜索注解,其父類上的被@Inherited注解過的注解會考慮在內(nèi)
【參考】@Inherited
2、Spring-IOC中的注解
2.1 、Autowired注解
按照byType注入,這是最核心的注解,左右就不說明了,直接看源碼
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
這里我們看到了元注解,說明所有的注解都是基于這四種元注解。
@Autowired 根據(jù)bean 類型從spring 上下文中進行查找,注冊類型必須唯一,否則報異常。與@Resource 的區(qū)別在于,@Resource 允許通過bean 名稱或bean 類型兩種方式進行查找@Autowired(required=false) 表示,如果spring 上下文中沒有找到該類型的bean 時, 才會使用new()的方式;
@Autowired 標注作用于 Map 類型時,如果 Map 的 key 為 String 類型,則 Spring 會將容器中所有類型符合 Map 的 value 對應的類型的 Bean 增加進來,用 Bean 的 id 或 name 作為 Map 的 key。
@Autowired 還有一個作用就是,如果將其標注在 BeanFactory 類型、ApplicationContext 類型、ResourceLoader 類型、ApplicationEventPublisher 類型、MessageSource 類型上,那么 Spring 會自動注入這些實現(xiàn)類的實例,不需要額外的操作。
2.2 @Qualifier
通常和 @Autowired一起使用
@Autowired
@Qualifier("softService")
private ISoftPMService softPMService;
- 說明
使用@Autowired 時,如果找到多個同一類型的bean,則會拋異常,此時可以使用 @Qualifier("beanName"),明確指定bean的名稱進行注入,此時與 @Resource指定name屬性作用相同。
2.3 @Resource
@Resource默認按照ByName自動注入
@Resource有兩個重要的屬性:name和type,而Spring將@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型
2.4、RequestMapping
這是springMVC中最常用的注解,在Spring4.0以后的版本推出了@GetMapping,@PostMapping,@PutMapping,@DeleteMapping等,這些是為restful風格提供的封裝注解,其實就是@RequestMapping和對應RequestMethod合并的注解。
- 作用 :@GetMapping = @RequestMapping(method = RequestMethod.GET)
- 說明:可以作用在類或者方法上,請求地址為類上的地址+方法上的地址
- 參數(shù)綁定說明:
如:http://localhost/user/list?userId=10&userName=tom
@GetMapping("/user/list")
public User getUser(User user){
···········
}
這樣userId和username會映射到user對應的屬性上。
2.5、@RequestParam,@PathVariable
用于綁定參數(shù),@PathVariable用于邦迪地址中rest風格的參數(shù),@RequestParam用于綁定普通提交的參數(shù)。
@PostMapping("/status/update/{id}")
public RestResult updateStatus(@PathVariable Long id, @RequestParam("status") Boolean status) {
··········
}
@RequestParam(value="id",required=false),required = faluse該參數(shù)非必須,默認為true
2.6、@Scope
該方法指定bean的創(chuàng)建類型,默認為單例,另外scope還有prototype、request、session、global session作用域。scope="prototype"多例
1.singleton : 全局有且僅有一個實例
2.prototype:每次獲取Bean的時候會有一個新的實例
3、request:request表示該針對每一次HTTP請求都會產(chǎn)生一個新的bean,同時該bean僅在當前HTTP request內(nèi)有效
4、session:session作用域表示該針對每一次HTTP請求都會產(chǎn)生一個新的bean,同時該bean僅在當前HTTP session內(nèi)有效
5、global session作用域類似于標準的HTTPSession作用域,不過它僅僅在基于portlet的web應用中才有意義
2.7、@Service,@Repository,@Component
用于標注業(yè)務層組件,可以看到該注解默認使用了@Component
【@Service】
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
String value() default "";
}
【@Repository】
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
String value() default "";
}
【@Component】
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
String value() default "";
}
由此可見這三個注解沒有功能沒有太大的區(qū)別,主要是用來標注業(yè)務,做業(yè)務方面的區(qū)分。
@Service用于標注業(yè)務層組件
@Repository用于標注數(shù)據(jù)訪問組件,即DAO組件
@Component泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
2.8、@Controller、@RestController
用于標注控制層組件即SpringMVC中的Controler
在4.0之后推出了@RestController其實就是@Controller和@ResponseBody的合集
2.9、@ResponseBody
該注解用于將Controller的方法返回的對象,通過適當?shù)腍ttpMessageConverter轉(zhuǎn)換為指定格式后,寫入到Response對象的body數(shù)據(jù)區(qū)。
作用域類或者方法上
【詳細參考】(http://www.cnblogs.com/fangjian0423/p/springMVC-request-param-analysis.html)
這塊詳細的到springMVC源碼分析的時候再講
3.0、@RequestBody
該注解用于讀取Request請求的body部分數(shù)據(jù),使用系統(tǒng)默認配置的HttpMessageConverter進行解析,然后把相應的數(shù)據(jù)綁定到要返回的對象上;
再把HttpMessageConverter返回的對象數(shù)據(jù)綁定到 controller中方法的參數(shù)上。
寫在最后
這一篇主要是寫了一些Sping的注解,下一篇講下配合SpingBoot推出的注解