Java注解(Annotation)中-示例

1、JDK自帶(java.lang)

"@Deprecated 和 @Override" 類似,"@Documented, @Inherited, @Retention, @Target" 類似。

1.1 @ Override

若某個(gè)方法被 @Override 的標(biāo)注,則意味著該方法會(huì)覆蓋父類中的同名方法。如果有方法被 @Override 標(biāo)示,但父類中卻沒有"被 @Override 標(biāo)注"的同名方法,則編譯器會(huì)報(bào)錯(cuò)。

public class OverrideTest {
    /**
     * toString() 在java.lang.Object中定義;
     * 因此,這里用 @Override 標(biāo)注是對的。
     */
    @Override
    public String toString(){
        return "Override toString";
    }

    /**
     * getString() 沒有在OverrideTest的任何父類中定義;
     * 但是,這里卻用 @Override 標(biāo)注,因此會(huì)產(chǎn)生編譯錯(cuò)誤!
     * 將 getString() 上面的 @Override注釋掉",即可解決該錯(cuò)誤。
     */
    @Override
    public String getString(){
        return "get toString";
    }
}

1.2 @Deprecated

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Deprecated {
/*
說明:
(01) @interface -- 它的用來修飾 Deprecated,意味著 Deprecated 實(shí)現(xiàn)了 java.lang.annotation.Annotation 接口;即 Deprecated 就是一個(gè)注解。 (02) @Documented -- 它的作用是說明該注解能出現(xiàn)在 javadoc 中。
(03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定 Deprecated 的策略是 RetentionPolicy.RUNTIME。這就意味著,編譯器會(huì)將Deprecated 的信息保留在 .class 文件中,并且能被虛擬機(jī)讀取。
(04) @Deprecated 所標(biāo)注內(nèi)容,不再被建議使用。
*/
}

比如,若某個(gè)方法被@Deprecated標(biāo)注,則該方法不在便建議使用,如果再用或者重寫該方法,編譯器會(huì)有相應(yīng)的警告信息:

public class DeprecatedTest {
    // @Deprecated 修飾 getString1(),表示 它是建議不被使用的函數(shù)
    @Deprecated
    private static void getString1(){
        System.out.println("Deprecated Method");
    }
    
    private static void getString2(){
        System.out.println("Normal Method");
    }
    
    // Date是日期/時(shí)間類。java已經(jīng)不建議使用該類了
    private static void testDate() {
        Date date = new Date(113, 8, 25);
        System.out.println(date.getYear());
    }
    // Calendar是日期/時(shí)間類。java建議使用Calendar取代Date表示"日期/時(shí)間"
    private static void testCalendar() {
        Calendar cal = Calendar.getInstance();
        System.out.println(cal.get(Calendar.YEAR));
    }
    
    public static void main(String[] args) {
        getString1(); //建議不再使用 getString1(); 
        getString2();//沒有被 @Deprecated 標(biāo)注,它的顯示正常;
        testDate(); //java 已經(jīng)建議不再使用;
        testCalendar();//調(diào)用了 Calendar 的 API 來操作日期/時(shí)間,java 建議用 Calendar 取代 Date。因此,操作 Calendar 不會(huì)產(chǎn)生 warning。
    }
}

1.3 @Inherited

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
/*
說明:
(01) @interface -- 它的用來修飾 Inherited,意味著 Inherited 實(shí)現(xiàn)了 java.lang.annotation.Annotation 接口;即 Inherited 就是一個(gè)注解。
(02) @Documented -- 它的作用是說明該注解能出現(xiàn)在 javadoc 中。
(03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定 Inherited 的策略是 RetentionPolicy.RUNTIME。這就意味著,編譯器會(huì)將 Inherited 的信息保留在 .class 文件中,并且能被虛擬機(jī)讀取。
(04) @Target(ElementType.ANNOTATION_TYPE) -- 它的作用是指定 Inherited 的類型是 ANNOTATION_TYPE。這就意味著,@Inherited 只能被用來標(biāo)注 "Annotation 類型"。
(05) @Inherited 的含義是,它所標(biāo)注的Annotation將具有繼承性。
*/
}

假設(shè),我們定義了某個(gè) Annotaion,它的名稱是 MyAnnotation,并且 MyAnnotation 被標(biāo)注為 @Inherited。現(xiàn)在,某個(gè)類 Base 使用了MyAnnotation,則 Base 具有了"具有了注解 MyAnnotation";現(xiàn)在,Sub 繼承了 Base,由于 MyAnnotation 是 @Inherited的(具有繼承性),所以,Sub 也 "具有了注解 MyAnnotation"。

/**
 * 自定義的Annotation。
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface Inheritable {
}

@Inheritable
class InheritableFather {
    public InheritableFather() {
        // InheritableBase是否具有 Inheritable Annotation
       System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));
    }
}

/**
 * InheritableSon 類只是繼承于 InheritableFather,
 */
public class InheritableSon extends InheritableFather {
    public InheritableSon() {
        super();    // 調(diào)用父類的構(gòu)造函數(shù)
        // InheritableSon類是否具有 Inheritable Annotation
        System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));
    }
    
    public static void main(String[] args)  {
        InheritableSon is = new InheritableSon();
    }
}

運(yùn)行結(jié)果:

InheritableFather:true
InheritableSon:true

現(xiàn)在,我們對 InheritableSon.java 進(jìn)行修改:注釋掉 "Inheritable 的 @Inherited 注解"。

InheritableFather:true
InheritableSon:false

對比上面的兩個(gè)結(jié)果,我們發(fā)現(xiàn):當(dāng)注解 Inheritable 被 @Inherited 標(biāo)注時(shí),它具有繼承性。否則,沒有繼承性。

1.4 @SuppressWarnings

/*
說明:
(01) @interface -- 它的用來修飾 SuppressWarnings,意味著 SuppressWarnings 實(shí)現(xiàn)了 java.lang.annotation.Annotation 接口;即 SuppressWarnings 就是一個(gè)注解。
(02) @Retention(RetentionPolicy.SOURCE) -- 它的作用是指定 SuppressWarnings 的策略是 RetentionPolicy.SOURCE。這就意味著,SuppressWarnings 信息僅存在于編譯器處理期間,編譯器處理完之后 SuppressWarnings 就沒有作用了。
(03) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -- 它的作用是指定 SuppressWarnings 的類型同時(shí)包括TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE。
TYPE 意味著,它能標(biāo)注"類、接口(包括注釋類型)或枚舉聲明"。
FIELD 意味著,它能標(biāo)注"字段聲明"。
METHOD 意味著,它能標(biāo)注"方法"。
PARAMETER 意味著,它能標(biāo)注"參數(shù)"。
CONSTRUCTOR 意味著,它能標(biāo)注"構(gòu)造方法"。
LOCAL_VARIABLE 意味著,它能標(biāo)注"局部變量"。
(04) String[] value(); 意味著,SuppressWarnings 能指定參數(shù)
(05) SuppressWarnings 的作用是,讓編譯器對"它所標(biāo)注的內(nèi)容"的某些警告保持靜默。
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

例如,"@SuppressWarnings(value={"deprecation", "unchecked"})" 表示對"它所標(biāo)注的內(nèi)容"中的 "SuppressWarnings 不再建議使用警告"和"未檢查的轉(zhuǎn)換時(shí)的警告"保持沉默。示例如下:

/*
SuppressWarnings 常用的關(guān)鍵字的表格
deprecation  -- 使用了不贊成使用的類或方法時(shí)的警告
unchecked    -- 執(zhí)行了未檢查的轉(zhuǎn)換時(shí)的警告,例如當(dāng)使用集合時(shí)沒有用泛型 (Generics) 來指定集合保存的類型。
fallthrough  -- 當(dāng) Switch 程序塊直接通往下一種情況而沒有 Break 時(shí)的警告。
path         -- 在類路徑、源文件路徑等中有不存在的路徑時(shí)的警告。
serial       -- 當(dāng)在可序列化的類上缺少 serialVersionUID 定義時(shí)的警告。
finally      -- 任何 finally 子句不能正常完成時(shí)的警告。
all          -- 關(guān)于以上所有情況的警告。
boxing      -- 禁止與裝箱/拆箱操作相關(guān)的警告
cast        -- 強(qiáng)制轉(zhuǎn)換以抑制與強(qiáng)制轉(zhuǎn)換操作相關(guān)的警告
dep-ann     -- 用于抑制相對于已棄用注釋的警告
hiding      -- 隱藏以抑制相對于隱藏變量的本地警告
incomplete-switch -- 在switch語句(enum案例)中,incomplete-switch用來抑制相對于丟失條目的警告
javadoc     -- 禁止與javadoc警告相關(guān)的警告
nls         -- 使用nls來抑制相對于非nls字符串的警告。
null        -- 空值來抑制相對于空值分析的警告
rawtypes    -- 拒絕與使用原始類型相關(guān)的警告
resource    -- 用于抑制與使用類型為Closeable的資源相關(guān)的警告的資源
restriction --限制禁止與使用不鼓勵(lì)或禁止引用相關(guān)的警告
static-access   --靜態(tài)訪問,抑制相對于不正確的靜態(tài)訪問的警告
static-method   --靜態(tài)方法,用于抑制相對于可以聲明為靜態(tài)的方法的警告
super       -- 超級-來抑制相對于在沒有超級調(diào)用的情況下重寫方法的警告
synthetic-access-- 用于抑制相對于內(nèi)部類的未優(yōu)化訪問的警告的合成訪問
sync-override   -- 在覆蓋同步方法時(shí),由于缺少同步而取消警告
unchecked       -- 未選中以抑制與未選中操作相關(guān)的警告
unqualified-field-access-- 不限定字段訪問來抑制與字段訪問不限定相關(guān)的警告
unused      -- 不常用來抑制與未使用代碼和死代碼相關(guān)的警告
*/
public class SuppressWarningTest {
//沒有使用 @SuppressWarnings(value={"deprecation"}) , 而 Date 屬于 java 不再建議使用的類。因此,調(diào)用 Date 的 API 時(shí),會(huì)產(chǎn)生警告。
    //@SuppressWarnings(value={"deprecation"})
    public static void doSomething() {
        Date date = new Date(113, 8, 26);
        System.out.println(date);
    }

    public static void main(String[] args) {
        doSomething();
    }
}

1.5 @SafeVarargs

堆污染警告。
出現(xiàn):使用泛型+可變參數(shù)的時(shí)候就會(huì)出現(xiàn)堆污染警告。

@SafeVarargs
    public static<T> T useVarargs(T... args){
        return args.length > 0?args[0]:null;
    }
    @Test
    public void testSafeVarargs(){
        System.out.println(useVarargs(Arrays.asList("s1","s2")));
    }

1.6 @FunctionalInterface

在Java SE 8中引入的 ,申明某個(gè)接口是函數(shù)式接口(函數(shù)式接口是就只含有一個(gè)抽象方法的接口)。加上該注解,當(dāng)你寫的接口不符合函數(shù)式接口定義的時(shí)候,編譯器會(huì)報(bào)錯(cuò)。該注解只是提醒編譯器去檢查該接口是否僅包含一個(gè)抽象方法。

@FunctionalInterface
    interface GreetingService  {
        void sayMessage(String message);
    }
//那么就可以使用Lambda表達(dá)式來表示該接口的一個(gè)實(shí)現(xiàn)(注:JAVA 8 之前一般是用匿名類實(shí)現(xiàn)的):
//GreetingService greetService1 = message -> System.out.println("Hello " + message);

2、第三方注解

2.1 基礎(chǔ)注解1(spring-context下org.springframework.stereotype)

2.1.1 @Component組合注解

用于標(biāo)注各個(gè)層級的注解,注入到spring容器管理。
@Controller @Service @Repository @Configuration 都是@Component組合注解,只是區(qū)分層級關(guān)系:

  • @Controller 標(biāo)注于控制層
  • @Service 標(biāo)注于業(yè)務(wù)層
  • @Repository 標(biāo)注于dao持久層
  • @Configuration 標(biāo)注于配置層
  • @Component 泛指組件,當(dāng)組件不好歸類時(shí)可用

2.1.1 @Bean

@Bean等價(jià)于<Bean></Bean>,添加的bean的id為方法名。

@Configuration
public class AppConfig {
    //@bean 也可以依賴其他任意數(shù)量的bean,如果TransferService 依賴 AccountRepository,我們可以通過方法參數(shù)實(shí)現(xiàn)這個(gè)依賴
    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

這個(gè)配置就等同于之前在xml里的配置:
@Configuration可理解為用spring的時(shí)候xml里面的<beans>標(biāo)簽
@Bean可理解為用spring的時(shí)候xml里面的<bean>標(biāo)簽

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"  depends-on="accountRepository"/>
</beans>

2.2 基礎(chǔ)注解2(spring-web下org.springframework.web.bind.annotation)

2.2.1 @ResponseBody

被注解的方法返回的結(jié)果直接寫入 HTTP 響應(yīng)正文(ResponseBody)中。
一般在異步獲取數(shù)據(jù)時(shí)使用,通常是在使用 @RequestMapping 后,返回值通常解析為跳轉(zhuǎn)路徑,加上 @Responsebody 后返回結(jié)果不會(huì)被解析為跳轉(zhuǎn)路徑,而是直接寫入HTTP 響應(yīng)正文中。

/***********************例子一*******************************/
@RequestMapping(value="user/login")
@ResponseBody
//將ajax(datas)發(fā)出的請求寫入U(xiǎn)ser對象中,返回json對象響應(yīng)回去
public User login(User user) {
    User user = new User();
    user.setUserid(1);
    user.setUsername("MrF");
    user.setStatus("1");    
    return user ;
}
/***********************例子二*******************************/
@Controller 
public class UserController {
    @GetMapping("/hello") 
    @ResponseBody public String hello() {
        return "hello spring"; 
    } 
}

2.2.2 @ RequestBody

將 HTTP 請求正文插入方法中,使用適合的 HttpMessageConverter 將請求體寫入某個(gè)對象。換句話就是:用于接收前端請求的Json參數(shù),并且封裝到對應(yīng)的JavaBean。

@RequestMapping(value = "user/login")
@ResponseBody
// 將ajax(datas)發(fā)出的請求寫入U(xiǎn)ser對象中
public User login(@RequestBody User user) {   
// 這樣就不會(huì)再被解析為跳轉(zhuǎn)路徑,而是直接將user對象寫入 HTTP 響應(yīng)正文中
    return user;    
}

提交時(shí), 根據(jù)request header Content-Type的值來判斷:

  • application/x-www-form-urlencoded -- 可選(GET,POST),必須(PUT)
    GET,POST -- 這種情況的數(shù)據(jù)@RequestParam,@ModelAttribute也可以處理,當(dāng)然@RequestBody也能處理
  • multipart/form-data -- 不能處理
    即使用@RequestBody不能處理這種格式的數(shù)據(jù)
  • 其他格式 -- 必須
    其他格式包括application/json,application/xml等。這些格式的數(shù)據(jù),必須使用@RequestBody來處理

2.2.3 @RequestMapping

用來處理請求地址映射的注解。

  • @GetMapping = @RequestMapping(method = RequestMethod.GET)
  • @PostMapping = @RequestMapping(method = RequestMethod.POST)
/**
RequestMapping注解有六個(gè)屬性,下面我們把她分成三類進(jìn)行說明。
1、value, method
value: 指定請求的實(shí)際地址,指定的地址可以是URI Template 模式(后面將會(huì)說明)
method:指定請求的method類型,GET、POST、PUT、DELETE等
2、consumes,produces
consumes: 指定處理請求的提交內(nèi)容類型(Content-Type),例如application/json, text/html;
produces: 指定返回的內(nèi)容類型,僅當(dāng)request請求頭中的(Accept)類型中包含該指定類型才返回;
3、params,headers
params:指定request中必須包含某些參數(shù)值是,才讓該方法處理。
headers:指定request中必須包含某些指定的header值,才能讓該方法處理請求。
*/
//用于類上,可以沒有
@RequestMapping(value = "/controllerDemo")
public class ControllerDemo {
    // 用于方法上,必須有
    @RequestMapping(value = "/methodDemo")    
    public String methodDemo() {
        return "helloWorld";
    }
}

2.2.4 @PathVariable、@RequestParam

用于接受前端url路徑參數(shù),通過路徑參數(shù)作為接口接受的參數(shù),Result風(fēng)格
區(qū)分:

  • @RequestParam -- URL是這樣的:http://host:port/path?參數(shù)名=參數(shù)值
  • @PathVariable -- URL是這樣的:http://host:port/path/參數(shù)值
//訪問路徑:localhost:8080/hello/1
@GetMapping("/hello/{id}")
public String func(@PathVariable String id) {
    return id;
}

2.2.5 @RequestParam

用于接受前端提交的參數(shù)。

//訪問路徑:localhost:8080/hello?name=張三
@GetMapping("/hello")
/*
String  value   name別名
String  name    請求參數(shù)對應(yīng)的屬性
boolean required    是否必傳
Stirng  defaultValue    默認(rèn)值
*/
public String func(@RequestParam(name = "name", required = false, defaultValue = "張三") String name) {
    return "OK";
}

2.2.6 @RestController

相當(dāng)于@ResponseBody + @Controller。

  • Controller中的方法無法返回jsp頁面,返回的內(nèi)容就是Return 里的內(nèi)容。

2.3 persistence注解(javax.persistence)

2.3.1 @Entity,@Table,@Column

@Entity表明該類是實(shí)體類,并且使用默認(rèn)的orm規(guī)則,即class名即數(shù)據(jù)庫表中表名,class字段名即表中的字段名。如果class名和數(shù)據(jù)庫表中名字不一致就用@Table,如果class字段名和表中的字段名不一直就用@Column

@Column用來標(biāo)識(shí)實(shí)體類中屬性與數(shù)據(jù)表中字段的對應(yīng)關(guān)系

  • name:被標(biāo)注字段在數(shù)據(jù)庫表中所對應(yīng)字段的名稱
  • unique:表示該字段是否為唯一標(biāo)識(shí),默認(rèn)為false。也可以使用@Table標(biāo)記中的@UniqueConstraint。
  • nullable:表示該字段是否可以為null值,默認(rèn)為true。
  • insertable:表示在使用“INSERT”腳本插入數(shù)據(jù)時(shí),是否需要插入該字段的值。
  • updatable:表示在使用“UPDATE”腳本插入數(shù)據(jù)時(shí),是否需要更新該字段的值。insertable和updatable屬性一般多用于只讀的屬性,例如主鍵和外鍵等。這些字段的值通常是自動(dòng)生成的。
  • columnDefinition:表示創(chuàng)建表時(shí),該字段創(chuàng)建的SQL語句,一般用于通過Entity生成表定義時(shí)使用。(也就是說,如果DB中表已經(jīng)建好,該屬性沒有必要使用。)
  • table:表示當(dāng)映射多個(gè)表時(shí),指定表的表中的字段。默認(rèn)值為主表的表名。
  • length:表示字段的長度,當(dāng)字段的類型為varchar時(shí),該屬性才有效,默認(rèn)為255個(gè)字符。
  • precision:和scaleprecision屬性和scale屬性表示精度,當(dāng)字段類型為double時(shí),precision表示數(shù)值的總長度,scale表示小數(shù)點(diǎn)所占的位數(shù)。

示例見2.3.2。

2.3.2 @Id,@Temporal,@GeneratedValue, @Generated

  • @Id表名該字段是主鍵,如果要開啟自增主鍵就用@GeneratedValue。
  • @Temporal幫Java的Date類型進(jìn)行格式化,一共有三種注解值:
    -- @Temporal(TemporalType.DATE)— yyyy-MM-dd的 Date類型
    -- @Temporal(TemporalType.TIME)—hh-MM-ss的 Date類型
    -- @Temporal(TemporalType.TIMESTAMP)—yyyy-MM-dd hh:MM:ss”的 Date類型
  • @Generated自動(dòng)生成:
    -- generated= never 標(biāo)明此屬性值不是從數(shù)據(jù)庫中生成
    -- generated默認(rèn)值是never
    -- generated= insert 標(biāo)明此屬性值在insert的時(shí)候生成,但是不會(huì)在隨后的 update時(shí)重新生成
    -- generated= always 標(biāo)明此屬性值在insert和update時(shí)都會(huì)被生成
@Entity
@Table(name = "batch")
public class Batch{

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Integer id;
    
    //在插入的時(shí)候自動(dòng)賦值當(dāng)前時(shí)間
    @Column(insertable = false)
    @Temporal(TemporalType.TIMESTAMP)   
    @Generated(GenerationTime.INSERT)   
    private Date createdTime;

    //自動(dòng)變化更新時(shí)間
    @Temporal(TemporalType.TIMESTAMP)
    @Column(insertable = false, updatable = false)
    @Generated(GenerationTime.ALWAYS)
    private Date updatedTime;
    
    //在插入的時(shí)候自動(dòng)賦值1
    @Column(insertable = false ,columnDefinition="Short default 1")
    @Generated(GenerationTime.INSERT)
    private Short status;
}

2.4 resteasy注解(jaxrs-api下javax.ws.rs)

resteasy 是java體系中比較成熟的rest框架,也是jax-rs規(guī)范的實(shí)現(xiàn)之一,dubbox的REST服務(wù)框架,就是采用的resteasy實(shí)現(xiàn)。

默認(rèn)情況下,resteasy使用jackson和jaxb來實(shí)現(xiàn)json及xml格式的序列化。應(yīng)用啟動(dòng)時(shí),會(huì)自動(dòng)掃描帶@Provider的包,找到最合適的provider。

這個(gè)可以用來做分布式,可以通過okhttp3協(xié)議來進(jìn)行交互。

2.4.1 @Path、@POST、@Produces、@Consumes、@Context

@Path("/td")
public interface PayIntegrationService {

    @Path("/pay")
    @POST
    @Produces({ ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
    @Consumes({ ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
    public JsonResponse pay(@Context HttpServletRequest request);
}

2.5 validation注解(validation-api下javax.validation)

用于前端請求參數(shù)校驗(yàn),@Valid需要配合BindingResult使用,以及配合下面各種校驗(yàn)注解進(jìn)行使用:

  • @Null 限制只能為null
  • @NotNull 限制必須不為null
  • @AssertFalse 限制必須為false
  • @AssertTrue 限制必須為true
  • @DecimalMax(value) 限制必須為一個(gè)不大于指定值的數(shù)字
  • @DecimalMin(value) 限制必須為一個(gè)不小于指定值的數(shù)字
  • @Digits(integer,fraction) 限制必須為一個(gè)小數(shù),且整數(shù)部分的位數(shù)不能超過integer,小數(shù)部分的位數(shù)不能超過fraction
  • @Future 限制必須是一個(gè)將來的日期
  • @Max(value) 限制必須為一個(gè)不大于指定值的數(shù)字
  • @Min(value) 限制必須為一個(gè)不小于指定值的數(shù)字
  • @Past 限制必須是一個(gè)過去的日期
  • @Pattern(value) 限制必須符合指定的正則表達(dá)式
  • @Size(max,min) 限制字符長度必須在min到max之間
  • @Past 驗(yàn)證注解的元素值(日期類型)比當(dāng)前時(shí)間早
  • @NotEmpty 驗(yàn)證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0)
  • @NotBlank 驗(yàn)證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時(shí)會(huì)去除字符串的空格
  • @Email 驗(yàn)證注解的元素值是Email,也可以通過正則表達(dá)式和flag指定自定義的email格式
/**
 * 接受前端的請求并且根據(jù)User實(shí)體類注解進(jìn)行校驗(yàn)
 */
@PostMapping("/hello/user")
public String hello(@Valid @RequestBody User user, BindingResult result) {
     if (result.hasErrors()) {
            result.getAllErrors().forEach(System.out::println);
     }
     System.out.println(user);
     return "hello spring";
}
@Data
public class User {
    @NotBlank(message = "用戶名不能為空")
    private String username;

    @NotBlank(message = "密碼名不能為空")
    private String password;
}

2.6 lombok常用注解

傳送門:lombok安裝和基本使用介紹

2.7 tkMapper注解

沒用過,以后更新。

2.8 springboot常用注解

2.8.1 @ConfigurationProperties

將配置文件中配置的每一個(gè)屬性的值,映射到這個(gè)組件中。

**
 * @ConfigurationProperties:
 *      prefix = "person":配置文件下面的所有屬性和類的屬性進(jìn)行一一映射
 *
 * 只有這個(gè)組件是容器中的組件,才能容器提供的@ConfigurationProperties功能;
 *
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {

    private String lastName;
    private Integer age;
    private Boolean boss;
    private Date birth;

    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
}

配置文件:

person:
    lastName: hello
    age: 18
    boss: false
    birth: 2017/12/12
    maps: {k1: v1,k2: 12}
    lists:
      - lisi
      - zhaoliu
    dog:
      name: 小狗
      age: 12

導(dǎo)入配置文件處理器,之后編寫配置就有提示了

<!--導(dǎo)入配置文件處理器,配置文件進(jìn)行綁定就會(huì)有提示-->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <optional>true</optional>
</dependency>

2.8.2 @MapperScan

掃描接口,放啟動(dòng)類上面

//掃描dao接口
@MapperScan("com.test.dao")
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

2.8.3 @ SpringBootApplication

SpringBootApplication啟動(dòng)時(shí)會(huì)默認(rèn)掃描主類當(dāng)前包及子包,如果需要掃描主類當(dāng)前包外的其他包就用@SpringBootApplication

//指定掃描的包
@SpringBootApplication(scanBasePackages = {"com.test"})

2.9 注入Bean的三個(gè)注解

@Autowired是spring自帶的,@Inject是JSR330規(guī)范實(shí)現(xiàn)的,@Resource是JSR250規(guī)范實(shí)現(xiàn)的,需要導(dǎo)入不同的包

@Autowired、@Inject用法基本一樣,不同的是@Autowired有一個(gè)request屬性

@Autowired、@Inject是默認(rèn)按照類型匹配的,@Resource是按照名稱匹配的

@Autowired如果需要按照名稱匹配需要和@Qualifier一起使用,@Inject和@Name一起使用

2.9.1 @Inject(javax.inject)

根據(jù)類型進(jìn)行自動(dòng)裝配的,默認(rèn)需要配置與變量名一致。如果需要按名稱進(jìn)行裝配,則需要配合@Named;
@Inject可以作用在變量、setter方法、構(gòu)造函數(shù)上

2.9.2 @Autowired ( org.springframework下sping-beans)

根據(jù)類型進(jìn)行自動(dòng)裝配的,名稱不一樣也沒事,如果需要按名稱進(jìn)行裝配,則需要配合@Qualifier;

@Autowired有個(gè)屬性為required,可以配置為false,如果配置為false之后,當(dāng)沒有找到相應(yīng)bean的時(shí)候,系統(tǒng)不會(huì)拋錯(cuò);

@Autowired可以作用在變量、setter方法、構(gòu)造函數(shù)上。

2.9.3 @Resource (jdk下rt.jar下的javax.annotation)

根據(jù)名稱進(jìn)行自動(dòng)裝配的,默認(rèn)需要配置與變量名一致,一般會(huì)指定一個(gè)name屬性。

@Resource可以作用在變量、setter方法上。

3、在反射中使用示例

/**
 * Annotation在反射函數(shù)中的使用示例
 */
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String[] value() default "unknown";
}

/**
 * Person類。它會(huì)使用MyAnnotation注解。
 */
class Person {
    
    /**
     * empty()方法同時(shí)被 "@Deprecated" 和 "@MyAnnotation(value={"a","b"})"所標(biāo)注 
     * (01) @Deprecated,意味著empty()方法,不再被建議使用
     * (02) @MyAnnotation, 意味著empty() 方法對應(yīng)的MyAnnotation的value值是默認(rèn)值"unknown"
     */
    @MyAnnotation
    @Deprecated
    public void empty(){
        System.out.println("\nempty");
    }
    
    /**
     * sombody() 被 @MyAnnotation(value={"girl","boy"}) 所標(biāo)注,
     * @MyAnnotation(value={"girl","boy"}), 意味著MyAnnotation的value值是{"girl","boy"}
     */
    @MyAnnotation(value={"girl","boy"})
    public void somebody(String name, int age){
        System.out.println("\nsomebody: "+name+", "+age);
    }
}

public class AnnotationTest {
    public static void main(String[] args) throws Exception {
        // 新建Person
        Person person = new Person();
        // 獲取Person的Class實(shí)例
        Class<Person> c = Person.class;
        // 獲取 somebody() 方法的Method實(shí)例
        Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});
        // 執(zhí)行該方法
        mSomebody.invoke(person, new Object[]{"lily", 18});
        iteratorAnnotations(mSomebody);
        

        // 獲取 somebody() 方法的Method實(shí)例
        Method mEmpty = c.getMethod("empty", new Class[]{});
        // 執(zhí)行該方法
        mEmpty.invoke(person, new Object[]{});        
        iteratorAnnotations(mEmpty);
    }
    
    public static void iteratorAnnotations(Method method) {

        // 判斷 somebody() 方法是否包含MyAnnotation注解
        if(method.isAnnotationPresent(MyAnnotation.class)){
            // 獲取該方法的MyAnnotation注解實(shí)例
            MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
            // 獲取 myAnnotation的值,并打印出來
            String[] values = myAnnotation.value();
            for (String str:values)
                System.out.printf(str+", ");
            System.out.println();
        }
        
        // 獲取方法上的所有注解,并打印出來
        Annotation[] annotations = method.getAnnotations();
        for(Annotation annotation : annotations){
            System.out.println(annotation);
        }
    }
}

運(yùn)行結(jié)果:

somebody: lily, 18
girl, boy, 
@cn.bcsoft.annotation.MyAnnotation(value=[girl, boy])

empty
unknown, 
@cn.bcsoft.annotation.MyAnnotation(value=[unknown])
@java.lang.Deprecated()

參考文檔:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容