前言
這段時(shí)間bug有點(diǎn)多,白天的時(shí)間幾乎都用在改bug了,近一個(gè)月都很少看書了爽航,得趕緊改完bug看書饭耳。在spring源碼分析結(jié)束之后衰腌,我們也已經(jīng)完成了循環(huán)依賴的解決方案以及設(shè)計(jì)模式,那么接下來(lái)我們分析下Spring中常用的注解饶囚。
這里先說(shuō)明下注解類型紫岩。
Annotition的類型使用關(guān)鍵字 @interface 而不是interface歇万。它繼承了java.lang.annotition.Annotition接口诅愚,并非申明了一個(gè)interface。
Annotation類型摹蘑、方法定義是獨(dú)特的、受限制的:
Annotation類型的方法必須申明為無(wú)參數(shù)制妄、無(wú)異常拋出的衔掸。這些方法定義了 Annotation的成員:方法名為成員名磷斧,而方法返回值為成員的類型。
特別的,如果方法名為 value()胳蛮, 則在注解的地方需要設(shè)置屬性值時(shí)可以直接寫入值抚垄,如:@Target({ElemenetType.TYPE}) 而不必寫為 @Target(value={ElemenetType.TYPE})
方法返回值必須為primitive類型浙滤、Class類型、枚舉類型揖膜、Annotation類型或者由前面類型之一作為元素的一位數(shù)組趁仙。
方法的后面可以使用default關(guān)鍵字加一個(gè)默認(rèn)數(shù)值來(lái)申明成員的默認(rèn)值薇组,null不能作為成員的默認(rèn)值炭菌,這與我們?cè)诜茿nnotation類型中定義方法有很大不同酌毡。
Annotation類型和他的方法不能使用Annotation類型的參數(shù)停团,成員不能是generic舌胶。只有返回值類型是Class的方法可以在Annotation類型中使用generic,因?yàn)榇朔椒軌蛴妙愞D(zhuǎn)換將各種類型轉(zhuǎn)換為Class洞辣。
Annotation類型又與接口有著近似之處:它可以定義常量、靜態(tài)成員類型(比如枚舉類型定義)沸久;Annotation類型也可以如接口一般被實(shí)現(xiàn)或者繼承挺峡。
1裳朋、元注解
元注解的作用就是負(fù)責(zé)注解其他注解暖眼。Java5.0定義了4個(gè)標(biāo)準(zhǔn)的meta-annotation類型,它們被用來(lái)提供對(duì)其它annotation類型作說(shuō)明 丧鸯。
- 1.@Target,
- 2.@Retention,
- 3.@Documented,
- 4.@Inherited
這些可以通過(guò)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
用于設(shè)定注解使用范圍
【詳細(xì)參考】@Target注解
Target通過(guò)ElementType來(lái)指定注解可使用范圍的枚舉集合。
- 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
定義注解的保留策略劝贸。
【詳細(xì)參考】@Retention
通過(guò)RetentionPolicy來(lái)指定注解的枚舉集合。
- RetentionPolicy.SOURCE :注解僅存在于源碼中宫补,在class字節(jié)碼文件中不包含
- RetentionPolicy.CLASS:默認(rèn)的保留策略虐秦,注解會(huì)在class字節(jié)碼文件中存在,但運(yùn)行時(shí)無(wú)法獲得
- RetentionPolicy.RUNTIME:注解會(huì)在class字節(jié)碼文件中存在抚太,在運(yùn)行時(shí)可以通過(guò)反射獲取到
1.3、@Documented
用于描述其它類型的annotation應(yīng)該被作為被標(biāo)注的程序成員的公共API捞稿,因此可以被例如javadoc此類的工具文檔化剩愧。Documented是一個(gè)標(biāo)記注解仁卷,沒(méi)有成員。
1.4橙垢、@Inherited
說(shuō)明子類可以繼承父類中的該注解
- 被@Inherited注解的注解只有在class上使用才會(huì)有“自動(dòng)繼承的特性”
- “自動(dòng)繼承的特性”是指如果在子類上搜索注解珍手,其父類上的被@Inherited注解過(guò)的注解會(huì)考慮在內(nèi)
【參考】@Inherited
2厦坛、Spring-IOC中的注解
2.1 五垮、Autowired注解
按照byType注入,這是最核心的注解杜秸,左右就不說(shuō)明了放仗,直接看源碼
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
這里我們看到了元注解,說(shuō)明所有的注解都是基于這四種元注解。
@Autowired 根據(jù)bean 類型從spring 上下文中進(jìn)行查找撬碟,注冊(cè)類型必須唯一诞挨,否則報(bào)異常。與@Resource 的區(qū)別在于呢蛤,@Resource 允許通過(guò)bean 名稱或bean 類型兩種方式進(jìn)行查找@Autowired(required=false) 表示惶傻,如果spring 上下文中沒(méi)有找到該類型的bean 時(shí), 才會(huì)使用new()的方式;
@Autowired 標(biāo)注作用于 Map 類型時(shí)其障,如果 Map 的 key 為 String 類型银室,則 Spring 會(huì)將容器中所有類型符合 Map 的 value 對(duì)應(yīng)的類型的 Bean 增加進(jìn)來(lái),用 Bean 的 id 或 name 作為 Map 的 key励翼。
@Autowired 還有一個(gè)作用就是蜈敢,如果將其標(biāo)注在 BeanFactory 類型、ApplicationContext 類型抚笔、ResourceLoader 類型扶认、ApplicationEventPublisher 類型、MessageSource 類型上殊橙,那么 Spring 會(huì)自動(dòng)注入這些實(shí)現(xiàn)類的實(shí)例辐宾,不需要額外的操作狱从。
2.2 @Qualifier
通常和 @Autowired一起使用
@Autowired
@Qualifier("softService")
private ISoftPMService softPMService;
- 說(shuō)明
使用@Autowired 時(shí),如果找到多個(gè)同一類型的bean叠纹,則會(huì)拋異常季研,此時(shí)可以使用 @Qualifier("beanName"),明確指定bean的名稱進(jìn)行注入誉察,此時(shí)與 @Resource指定name屬性作用相同与涡。
2.3 @Resource
@Resource默認(rèn)按照ByName自動(dòng)注入
@Resource有兩個(gè)重要的屬性:name和type,而Spring將@Resource注解的name屬性解析為bean的名字持偏,而type屬性則解析為bean的類型
2.4驼卖、RequestMapping
這是springMVC中最常用的注解,在Spring4.0以后的版本推出了@GetMapping,@PostMapping,@PutMapping,@DeleteMapping等鸿秆,這些是為restful風(fēng)格提供的封裝注解酌畜,其實(shí)就是@RequestMapping和對(duì)應(yīng)RequestMethod合并的注解。
- 作用 :@GetMapping = @RequestMapping(method = RequestMethod.GET)
- 說(shuō)明:可以作用在類或者方法上卿叽,請(qǐng)求地址為類上的地址+方法上的地址
- 參數(shù)綁定說(shuō)明:
如:http://localhost/user/list?userId=10&userName=tom
@GetMapping("/user/list")
public User getUser(User user){
···········
}
這樣userId和username會(huì)映射到user對(duì)應(yīng)的屬性上桥胞。
2.5、@RequestParam考婴,@PathVariable
用于綁定參數(shù)贩虾,@PathVariable用于邦迪地址中rest風(fēng)格的參數(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ù)非必須,默認(rèn)為true
2.6喳钟、@Scope
該方法指定bean的創(chuàng)建類型屁使,默認(rèn)為單例,另外scope還有prototype、request奔则、session蛮寂、global session作用域。scope="prototype"多例
1.singleton : 全局有且僅有一個(gè)實(shí)例
2.prototype:每次獲取Bean的時(shí)候會(huì)有一個(gè)新的實(shí)例
3易茬、request:request表示該針對(duì)每一次HTTP請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的bean酬蹋,同時(shí)該bean僅在當(dāng)前HTTP request內(nèi)有效
4、session:session作用域表示該針對(duì)每一次HTTP請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的bean抽莱,同時(shí)該bean僅在當(dāng)前HTTP session內(nèi)有效
5范抓、global session作用域類似于標(biāo)準(zhǔn)的HTTPSession作用域,不過(guò)它僅僅在基于portlet的web應(yīng)用中才有意義
2.7食铐、@Service匕垫,@Repository,@Component
用于標(biāo)注業(yè)務(wù)層組件,可以看到該注解默認(rèn)使用了@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 "";
}
由此可見(jiàn)這三個(gè)注解沒(méi)有功能沒(méi)有太大的區(qū)別虐呻,主要是用來(lái)標(biāo)注業(yè)務(wù)象泵,做業(yè)務(wù)方面的區(qū)分寞秃。
@Service用于標(biāo)注業(yè)務(wù)層組件
@Repository用于標(biāo)注數(shù)據(jù)訪問(wèn)組件,即DAO組件
@Component泛指組件偶惠,當(dāng)組件不好歸類的時(shí)候春寿,我們可以使用這個(gè)注解進(jìn)行標(biāo)注。
2.8忽孽、@Controller绑改、@RestController
用于標(biāo)注控制層組件即SpringMVC中的Controler
在4.0之后推出了@RestController其實(shí)就是@Controller和@ResponseBody的合集
2.9、@ResponseBody
該注解用于將Controller的方法返回的對(duì)象兄一,通過(guò)適當(dāng)?shù)腍ttpMessageConverter轉(zhuǎn)換為指定格式后厘线,寫入到Response對(duì)象的body數(shù)據(jù)區(qū)。
作用域類或者方法上
【詳細(xì)參考】(http://www.cnblogs.com/fangjian0423/p/springMVC-request-param-analysis.html)
這塊詳細(xì)的到springMVC源碼分析的時(shí)候再講
3.0出革、@RequestBody
該注解用于讀取Request請(qǐng)求的body部分?jǐn)?shù)據(jù)皆的,使用系統(tǒng)默認(rèn)配置的HttpMessageConverter進(jìn)行解析,然后把相應(yīng)的數(shù)據(jù)綁定到要返回的對(duì)象上蹋盆;
再把HttpMessageConverter返回的對(duì)象數(shù)據(jù)綁定到 controller中方法的參數(shù)上。
寫在最后
這一篇主要是寫了一些Sping的注解硝全,下一篇講下配合SpingBoot推出的注解