国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java自定義注解

這篇具有很好參考價(jià)值的文章主要介紹了Java自定義注解。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

一、什么是自定義注解

1)Java注解簡(jiǎn)介

2)Java注解分類

JDK基本注解

JDK元注解

自定義注解

如何自定義注解?

二、自定義注解

1)獲取類上注解值

2)獲取類屬性上的注解屬性值

3)獲取方法上的注解值?

4)獲取參數(shù)修飾注解對(duì)應(yīng)的屬性值

三、aop應(yīng)用自定義注解

自定義注解日志的使用


一、什么是自定義注解

1)Java注解簡(jiǎn)介

Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運(yùn)行時(shí)進(jìn)行解析和使用,起到說(shuō)明、配置的功能,注解相關(guān)類都包含在java.lang.annotation包中。

2)Java注解分類

JDK基本注解
JDK元注解
自定義注解

JDK基本注解

@Override
重寫

@SuppressWarnings(value = "unchecked")
壓制編輯器警告

JDK元注解

@Retention:定義注解的保留策略
@Retention(RetentionPolicy.SOURCE)             //注解僅存在于源碼中,在class字節(jié)碼文件中不包含
@Retention(RetentionPolicy.CLASS)              //默認(rèn)的保留策略,注解會(huì)在class字節(jié)碼文件中存在,但運(yùn)行時(shí)無(wú)法獲得,
@Retention(RetentionPolicy.RUNTIME)            //注解會(huì)在class字節(jié)碼文件中存在,在運(yùn)行時(shí)可以通過(guò)反射獲取到

@Target:指定被修飾的Annotation可以放置的位置(被修飾的目標(biāo))
@Target(ElementType.TYPE)                      //接口、類
@Target(ElementType.FIELD)                     //屬性
@Target(ElementType.METHOD)                    //方法
@Target(ElementType.PARAMETER)                 //方法參數(shù)
@Target(ElementType.CONSTRUCTOR)               //構(gòu)造函數(shù)
@Target(ElementType.LOCAL_VARIABLE)            //局部變量
@Target(ElementType.ANNOTATION_TYPE)           //注解
@Target(ElementType.PACKAGE)                   //包
注:可以指定多個(gè)位置,例如:
@Target({ElementType.METHOD, ElementType.TYPE}),也就是此注解可以在方法和類上面使用

@Inherited:指定被修飾的Annotation將具有繼承性

@Documented:指定被修飾的該Annotation可以被javadoc工具提取成文檔.

自定義注解

注解分類(根據(jù)Annotation是否包含成員變量,可以把Annotation分為兩類):

標(biāo)記Annotation:
沒(méi)有成員變量的Annotation; 這種Annotation僅利用自身的存在與否來(lái)提供信息

元數(shù)據(jù)Annotation:
包含成員變量的Annotation; 它們可以接受(和提供)更多的元數(shù)據(jù);

如何自定義注解?

使用@interface關(guān)鍵字, 其定義過(guò)程與定義接口非常類似, 需要注意的是:
? ?Annotation的成員變量在Annotation定義中是以無(wú)參的方法形式來(lái)聲明的, 其方法名和返回值類型定義了該成員變量的名字和類型,
? ?而且我們還可以使用default關(guān)鍵字為這個(gè)成員變量設(shè)定默認(rèn)值;

二、自定義注解

常見的自定義注解有四種:注解用在類上面、注解用在方法上面、注解用在屬性上面、注解用在參數(shù)上面

?@Target

java自定義注解,java,開發(fā)語(yǔ)言

?java自定義注解,java,開發(fā)語(yǔ)言

?@Target里面標(biāo)記的屬性,決定了你自定義注解能放在哪里使用,將METHOD改為TEPY或者使用逗號(hào)分隔在后面添加也行,這樣方法,類,屬性都可以使用這個(gè)注解類了

java自定義注解,java,開發(fā)語(yǔ)言

java自定義注解,java,開發(fā)語(yǔ)言??

如果不知道該注解是干嘛用的,可以點(diǎn)進(jìn)去查看,Ctrl+鼠標(biāo)鍵?

java自定義注解,java,開發(fā)語(yǔ)言

@Retention一共有三種:source、class、runtime?

如果屬性是value的話,可以省略value=?

java自定義注解,java,開發(fā)語(yǔ)言

1)獲取類上注解值

使用自定義注解就是為了拿這上面的數(shù)據(jù)的?

java自定義注解,java,開發(fā)語(yǔ)言

MyAnnotation1.java?

package com.xiaokun.ssm.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * @author 小坤
 * @create  2022-10-28 20:09
 */
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
 
//    指的是注解中的屬性
    public String desc() default "desc可以修飾符、方法、屬性";
    public String value() default "value可以修飾符、方法、屬性";
}
 
 

?MyAnnotation2.java?

package com.xiaokun.ssm.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * @author 小坤
 * @create  2022-10-28 20:09
 */
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation2 {
 
//    指的是注解中的屬性
    public String desc() default "desc可以修飾符、方法、屬性";
    public String value() default "value可以修飾符、方法、屬性";
}

Studentcontroller.java

package com.xiaokun.ssm.annotation;
 
/**
 * @author 小坤
 * @create  2022-10-28 20:11
 */
@MyAnnotation1(desc = "標(biāo)記在類上面")
public class Studentcontroller {
 
    @MyAnnotation1("標(biāo)記在屬性id上面")
    private String id;
    @MyAnnotation1("標(biāo)記在屬性name上面")
    private String name;
    @MyAnnotation1
    public void test1(@MyAnnotation2("用來(lái)修飾id參數(shù)") String id,@MyAnnotation2("用來(lái)修飾name參數(shù)") String name){
        System.out.println("測(cè)試...");
    }
 
 
 
}

Demo1.java

package com.jwj.ssm.annotation.demo;
 
import com.xiaokun.ssm.annotation.MyAnnotation1;
import com.xiaokun.ssm.annotation.Studentcontroller;
 
/**
 * @author 小坤
 * @create  2022-10-28 22:10
 *
 * 目標(biāo):
 * 1.獲取studentController 類上自定義注解 中的內(nèi)容
 * 2.獲取studentController 方法上自定義注解 中的內(nèi)容
 * 3.獲取studentController 屬性上自定義注解 中的內(nèi)容
 * 4.獲取studentController 參數(shù)上自定義注解 中的內(nèi)容
 * * *..*Service.*pager(..)
 * com.zking.service.BookService.queryPager(..);
 * com.zking.service.OrderService.queryPager(..);
 */
public class Demo1 {
    public static void main(String[] args) {
//        拿到類、拿注解
        MyAnnotation1 annotation = Studentcontroller.class.getAnnotation(MyAnnotation1.class);
        System.out.println(annotation.value());
        System.out.println(annotation.desc());
    }
}

這個(gè)時(shí)候我們運(yùn)行main方法時(shí),程序會(huì)報(bào)錯(cuò),圖中詳講,看圖???

java自定義注解,java,開發(fā)語(yǔ)言

java自定義注解,java,開發(fā)語(yǔ)言

2)獲取類屬性上的注解屬性值

Demo1.java??

package com.xiaokun.ssm.annotation.demo;
 
import com.xiaokun.ssm.annotation.MyAnnotation1;
import com.xiaokun.ssm.annotation.MyAnnotation2;
import com.xiaokun.ssm.annotation.Studentcontroller;
 
import java.lang.reflect.Field;
 
/**
 * @author 小坤
 * @create  2022-10-28 22:10
 *
 * 目標(biāo):
 * 1.獲取studentController 類上自定義注解 中的內(nèi)容
 * 2.獲取studentController 方法上自定義注解 中的內(nèi)容
 * 3.獲取studentController 屬性上自定義注解 中的內(nèi)容
 * 4.獲取studentController 參數(shù)上自定義注解 中的內(nèi)容
 * * *..*Service.*pager(..)
 * com.zking.service.BookService.queryPager(..);
 * com.zking.service.OrderService.queryPager(..);
 */
public class Demo1 {
    public static void main(String[] args) throws NoSuchFieldException {
//        拿到類、拿注解
        MyAnnotation1 annotation = Studentcontroller.class.getAnnotation(MyAnnotation1.class);
        System.out.println(annotation.value());
        System.out.println(annotation.desc());
 
//        獲取屬性上的
        Field id = Studentcontroller.class.getDeclaredField("id");
        Field name = Studentcontroller.class.getDeclaredField("name");
        System.out.println(id.getAnnotation(MyAnnotation1.class).value());
        System.out.println(name.getAnnotation(MyAnnotation1.class).value());
 


    }
}

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

java自定義注解,java,開發(fā)語(yǔ)言

3)獲取方法上的注解值?

// ? ? ? ?獲取到方法上的
? ? ? ? Method m1 = Studentcontroller.class.getDeclaredMethod("test1", String.class, String.class);
? ? ? ? System.out.println(m1.getAnnotation(MyAnnotation1.class).value());

4)獲取參數(shù)修飾注解對(duì)應(yīng)的屬性值

//        獲取參數(shù)上的標(biāo)識(shí)
        for (Parameter p : m1.getParameters()) {
            System.out.println(p.getAnnotation(MyAnnotation2.class).value());
 
        }

三、aop應(yīng)用自定義注解

在做一個(gè)系統(tǒng)中,有時(shí)需要記錄操作日志,方便找到某個(gè)操作是誰(shuí)進(jìn)行的,這個(gè)可以用spring的aop來(lái)實(shí)現(xiàn),本篇博客記錄用自定義注解+aop應(yīng)用于springboot項(xiàng)目中實(shí)現(xiàn)操作日志的記錄

aop相關(guān)術(shù)語(yǔ)介紹

  • 連接點(diǎn)(Joinpoint): 程序執(zhí)行的某個(gè)特定位置,如某個(gè)方法調(diào)用前,調(diào)用后,方法拋出異常后,這些代碼中的特定點(diǎn)稱為連接點(diǎn);簡(jiǎn)單來(lái)說(shuō),就是在哪加入你的邏輯增強(qiáng),連接點(diǎn)表示具體要攔截的方法,切點(diǎn)是定義一個(gè)范圍,而連接點(diǎn)是具體到某個(gè)方法
  • 切點(diǎn)(PointCut):每個(gè)程序的連接點(diǎn)有多個(gè),如何定位到某個(gè)感興趣的連接點(diǎn),就需要通過(guò)切點(diǎn)來(lái)定位。比如,連接點(diǎn)是數(shù)據(jù)庫(kù)的記錄,切點(diǎn)是查詢條件;切點(diǎn)用于來(lái)限定Spring-AOP啟動(dòng)的范圍,通常我們采用表達(dá)式的方式來(lái)設(shè)置,所以關(guān)鍵詞是范圍
  • 增強(qiáng)(Advice):增強(qiáng)是織入到目標(biāo)類連接點(diǎn)上的一段程序代碼;在Spring中,像BeforeAdvice等還帶有方位信息;通知是直譯過(guò)來(lái)的結(jié)果,我個(gè)人感覺叫做“業(yè)務(wù)增強(qiáng)”更合適,對(duì)照代碼就是攔截器定義的相關(guān)方法,通知分為如下幾種:
  1. 前置通知(before):在執(zhí)行業(yè)務(wù)代碼前做些操作,比如獲取連接對(duì)象
  2. 后置通知(after):在執(zhí)行業(yè)務(wù)代碼后做些操作,無(wú)論是否發(fā)生異常,它都會(huì)執(zhí)行,比如關(guān)閉連接對(duì)象
  3. 異常通知(afterThrowing):在執(zhí)行業(yè)務(wù)代碼后出現(xiàn)異常,需要做的操作,比如回滾事務(wù)
  4. 返回通知(afterReturning):在執(zhí)行業(yè)務(wù)代碼后無(wú)異常,會(huì)執(zhí)行的操作
  5. 環(huán)繞通知(around):環(huán)繞通知可以在方法調(diào)用前后完成自定義的行為,它也會(huì)選擇是否繼續(xù)執(zhí)行連接點(diǎn)或直接返回它們自己的返回值或拋出異常來(lái)結(jié)束執(zhí)行
    ?

目標(biāo)對(duì)象(Target):需要被加強(qiáng)的業(yè)務(wù)對(duì)象

織入(Weaving):織入就是將增強(qiáng)添加到對(duì)目標(biāo)類具體連接點(diǎn)上的過(guò)程;織入是一個(gè)形象的說(shuō)法,具體來(lái)說(shuō),就是生成代理對(duì)象并將切面內(nèi)容融入到業(yè)務(wù)流程的過(guò)程。

代理類(Proxy):一個(gè)類被AOP織入增強(qiáng)后,就產(chǎn)生了一個(gè)代理類

切面(Aspect):切面由切點(diǎn)和增強(qiáng)組成,它既包括了橫切邏輯的定義,也包括了連接點(diǎn)的定義,SpringAOP就是將切面所定義的橫切邏輯織入到切面所制定的連接點(diǎn)中。SpringAOP將切面定義的內(nèi)容織入到我們的代碼中,從而實(shí)現(xiàn)前后的控制邏輯。 比如我們常寫的攔截器Interceptor,就是一個(gè)切面類

自定義注解日志的使用

DemoController.java

package com.xiaokun.ssm.annotation.aop;
 
import org.springframework.stereotype.Controller;
 
/**
 * @author 小坤
 * @create  2022-10-29 14:19
 */
@Controller
public class DemoController {
    @MyLog(desc = "這是一個(gè)測(cè)試類的方法")
    public void test(){
        System.out.println("測(cè)試方法");
    }
}

MyLog.java

package com.xiaokun.ssm.annotation.aop;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    String desc();
}

MyLogAspect?.java

package com.xiaokun.ssm.annotation.aop;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
 
@Component
@Aspect
public class MyLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);
 
    /**
     * 只要用到了com.javaxl.p2.annotation.springAop.MyLog這個(gè)注解的,就是目標(biāo)類
     */
    @Pointcut("@annotation(com.jwj.ssm.annotation.aop.MyLog)")
//    這是以前的寫法 @Around("execution"(* *..*Service.*Pager(..))")
//   上面這個(gè)已經(jīng)把這個(gè)替代掉了 @Pointcut("@execution(* *.*Controller.add())")
    private void MyValid() {
    }
 
    @Before("MyValid()")
    public void before(JoinPoint joinPoint) {
//        joinPoint
//        目標(biāo)對(duì)象、目標(biāo)方法、傳遞的參數(shù)
 
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        logger.debug("[" + signature.getName() + " : start.....]");
        System.out.println("[" + signature.getName() + " : start.....]");
 
        MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
        logger.debug("【目標(biāo)對(duì)象方法被調(diào)用時(shí)候產(chǎn)生的日志,記錄到日志表中】:"+myLog.desc());
        System.out.println("【目標(biāo)對(duì)象方法被調(diào)用時(shí)候產(chǎn)生的日志,記錄到日志表中】:" + myLog.desc());
    }
}

java自定義注解,java,開發(fā)語(yǔ)言

?添加測(cè)試方法

AnnotationTest.java

package com.xiaokun.shiro;
 
import com.xiaokun.ssm.annotation.aop.DemoController;
import com.xiaokun.ssm.biz.ClazzBiz;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
/**
 * @author 小坤
 * @create  2022-10-27 22:21
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext.xml"})
public class AnnotationTest {
    @Autowired
    private DemoController demoController;
 
    @Test
    public void test1(){
        demoController.test();
    }
}

java自定義注解,java,開發(fā)語(yǔ)言文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-826083.html

到了這里,關(guān)于Java自定義注解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Java實(shí)現(xiàn)自定義注解

    Java實(shí)現(xiàn)自定義注解

    (1)Java實(shí)現(xiàn)自定義注解其實(shí)很簡(jiǎn)單,跟類定義差不多,只是屬性的定義可能跟我們平時(shí)定義的屬性略有不同,這里會(huì)給大家詳解,先來(lái)看代碼: 上面代碼就實(shí)現(xiàn)了一個(gè) 自定義注解 , 實(shí)現(xiàn)自定義注解需要最少指定 兩個(gè) 基本條件 : ①注解的作用范圍②注解的生命周期 ,那

    2023年04月19日
    瀏覽(24)
  • Java中自定義注解

    當(dāng)使用Java編寫應(yīng)用程序時(shí),我們常常使用注解來(lái)為程序添加附加信息,并且可以在運(yùn)行時(shí)讀取這些注解。除了Java提供的預(yù)定義注解外,我們還可以自定義注解來(lái)滿足自己的需求。在本文中,我們將介紹Java中自定義注解的基礎(chǔ)知識(shí)。 一、什么是注解? 注解是一種元數(shù)據(jù),可

    2024年02月14日
    瀏覽(24)
  • Java自定義注解

    Java自定義注解

    目錄 一、什么是自定義注解 1)Java注解簡(jiǎn)介 2)Java注解分類 JDK基本注解 JDK元注解 自定義注解 如何自定義注解? 二、自定義注解 1)獲取類上注解值 2)獲取類屬性上的注解屬性值 3)獲取方法上的注解值? 4)獲取參數(shù)修飾注解對(duì)應(yīng)的屬性值 三、aop應(yīng)用自定義注解 自定義注

    2024年02月19日
    瀏覽(20)
  • Java的自定義注解

    Java的自定義注解

    ????????自定義注解包括注解聲明、元注解、運(yùn)行時(shí)處理器三個(gè)部分。注解聲明指定了注解的名稱、作用域、成員等信息;元注解則用來(lái)對(duì)注解進(jìn)行修飾;運(yùn)行時(shí)處理器則負(fù)責(zé)在程序運(yùn)行過(guò)程中處理注解,并根據(jù)注解提供的信息執(zhí)行相應(yīng)的邏輯。自定義注解在編寫框架、插

    2024年02月03日
    瀏覽(24)
  • 一文詳解Java自定義注解

    一文詳解Java自定義注解

    目錄 簡(jiǎn)介 JDK注解 @Target @Retention @Documented @Inherited 第三方注解 自定義注解 舉例 默認(rèn)字符串注解 實(shí)現(xiàn)指定包名稱掃描注解 注解( Annotation )是Java SE 5.0 版本開始引入的概念,它是對(duì) Java 源代碼的說(shuō)明,是一種元數(shù)據(jù)(描述數(shù)據(jù)的數(shù)據(jù))。 Java中的注解主要分為以下三類: JDK的

    2024年02月06日
    瀏覽(59)
  • Java注解源碼分析,實(shí)現(xiàn)自定義注解通過(guò)反射獲取

    JDK5.0 引入,可以通過(guò)反射機(jī)制動(dòng)態(tài)獲取,大量應(yīng)用于java框架中 內(nèi)置注解 @Override 重寫父類方法時(shí) @Deprecated 使用它存在風(fēng)險(xiǎn),可能導(dǎo)致錯(cuò)誤 可能在未來(lái)版本中不兼容 可能在未來(lái)版本中刪除 一個(gè)更好和更高效的方案已經(jīng)取代它 @SuppressWarnings 告訴編譯器忽略指定的警告,不用在

    2024年02月03日
    瀏覽(21)
  • java 自定義xss校驗(yàn)注解實(shí)現(xiàn)

    java 自定義xss校驗(yàn)注解實(shí)現(xiàn)

    自定義一個(gè)注解@Xss。名字隨意 validator校驗(yàn)類:XssValidator。這個(gè)校驗(yàn)類要和上面的@Xss注解上的 @Constraint(validatedBy = { XssValidator.class })對(duì)應(yīng) 具體使用在某個(gè)字段上加上注解;形如: 然后在控制層中增加@Validated注解校驗(yàn)就可以了 ?以上代碼實(shí)現(xiàn)后。會(huì)自動(dòng)針對(duì)某些增加了@Xss字符

    2024年02月14日
    瀏覽(22)
  • Java Validation 只能輸入固定值(自定義校驗(yàn)注解、@Pattern)

    方法一: 自定義校驗(yàn)注解 注解接口: DTO使用: type只能輸入數(shù)字 1 、 2 typeMean只能輸入字符串“ 單位 ”、“ 專家 ” 方法二: @Pattern注解 只能校驗(yàn) 字符串 ,正則表達(dá)式為:“ 單位|專家 ” typeMean只能輸入字符串“ 單位 ”、“ 專家 ”

    2024年01月25日
    瀏覽(20)
  • Java自定義校驗(yàn)注解實(shí)現(xiàn)List、set集合字段唯一性校驗(yàn)

    Java自定義校驗(yàn)注解實(shí)現(xiàn)List、set集合字段唯一性校驗(yàn)

    在開發(fā)過(guò)程中,前端給后端傳遞集合,并且需要保證集合的實(shí)體類中的某些字段必須是惟一的,不能重復(fù)。 傳遞的集合: 集合對(duì)應(yīng)的實(shí)體類: 如果我們要保證傳遞的name或者card必須是唯一的,不能重復(fù),應(yīng)該如何實(shí)現(xiàn)呢,此時(shí)可以通過(guò)自定義注解的方式實(shí)現(xiàn)。 @Documented @Do

    2024年02月14日
    瀏覽(57)
  • Java注解開發(fā)

    注解提供了更聲明式和方便的方式,而編碼方式允許更精細(xì)的控制和定制。 在Java中,當(dāng)Redis充當(dāng)緩存時(shí),使用注解的方式更為常見和方便。Spring Framework提供了一種基于注解的緩存機(jī)制,稱為Spring Cache。通過(guò)在方法上添加注解,開發(fā)人員可以指定緩存的行為,例如緩存的名稱

    2024年02月14日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包