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

Java AOP 通過注解實(shí)現(xiàn)切面及通過注解改變返回值

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

Java AOP 通過注解實(shí)現(xiàn)切面及通過注解改變返回值

AOP簡(jiǎn)介

學(xué)習(xí)過java的小伙伴都知道Spring的重要知識(shí)點(diǎn)之一就是AOP,AOP也就是切面編程,切面編程它能夠幫助我們實(shí)現(xiàn)非侵入式的功能增強(qiáng),解耦現(xiàn)有的業(yè)務(wù)邏輯和要新增的功能增強(qiáng)。

實(shí)際應(yīng)用中的場(chǎng)景

事務(wù)管理、攔截器、日志處理、權(quán)限控制等。

AOP的增強(qiáng)方式

前置增強(qiáng)、后置增強(qiáng)、異常增強(qiáng)、環(huán)繞增強(qiáng)

AOP的通知方式及執(zhí)行順序

通知方式:前置通知、后置通知、環(huán)繞通知、返回通知、異常通知。

執(zhí)行順序:前置通知、環(huán)繞通知,如果發(fā)生異常執(zhí)行異常通知,如果沒有發(fā)生異常執(zhí)行后置通知(after),最后執(zhí)行返回通知(afterReturning)。

AOP實(shí)戰(zhàn)

假設(shè)場(chǎng)景1

查詢學(xué)生類(包括證件類型、證件號(hào)、性別、名稱等),如果證件類型為 “01” ,也就是身份證,那么性別由身份證第17位決定,即使數(shù)據(jù)庫(kù)有性別字段值,也會(huì)被覆蓋,證件類型不是**“01”**身份證,則不做處理,性別為數(shù)據(jù)庫(kù)存儲(chǔ)的性別。

處理邏輯1

自定義一個(gè)注解SexType,用在方法上,寫一個(gè)切面類,切點(diǎn)就是SexType注解,在返回通知(afterReturning)階段進(jìn)行增強(qiáng)。

實(shí)現(xiàn)邏輯1

定義SexType注解:

@Inherited
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SexType {

}

使用SexType的示例:

	@SexType
    public Students selectById(Integer id) {
        Students students = studentsMapper.selectById(id);
        return students;
    }

切面類StudentAop:

@Aspect
@Component
@Order(1)
public class StudentAop {

    @Pointcut(value = "@annotation(com.qiaofc.sharding.aop.SexType)")
    private void setSex() {}

    @Around("setSex()")
    public static Object logStart(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("執(zhí)行切面");
        return joinPoint.proceed();
    }
    @AfterReturning(value = "setSex()",returning = "methodResult")
    public static void setSexType(JoinPoint joinPoint, Object methodResult) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        String sexResult = "";
        //拿到setSex方法,方便后面通過反射調(diào)用sexSex方法給屬性賦值
        Method setSex = methodResult.getClass().getMethod("setSex", String.class);
        //拿到屬性值
        Field fieldIdentifyType = methodResult.getClass().getDeclaredField("identifyType");
        //設(shè)置為true可以拿到private的屬性值,否則拿不到
        fieldIdentifyType.setAccessible(true);
        String identifyType = (String)fieldIdentifyType.get(methodResult);

        Field fieldIdentifyNumber = methodResult.getClass().getDeclaredField("identifyNumber");
        fieldIdentifyNumber.setAccessible(true);
        String identifyNumber = (String)fieldIdentifyNumber.get(methodResult);

        Field fieldSex = methodResult.getClass().getDeclaredField("sex");
        fieldSex.setAccessible(true);
        String sex = (String)fieldSex.get(methodResult);

        if (methodResult != null) {
            if ("01".equals(identifyType) && !StringUtils.isEmpty(identifyNumber) && identifyNumber.length() == 18) {
                String sexN = identifyNumber.substring(16,17);
                try {
                    int sexI = Integer.valueOf(sexN);
                    if (sexI % 2 == 1) {
                        sexResult = "男";
                    } else {
                        sexResult = "女";
                    }
                } catch (Exception e) {
                    sexResult = "";
                }
            }
            if (StringUtils.isEmpty(sexResult)) {
                if (!StringUtils.isEmpty(sex)) {
                    if ("0".equals(sex)) {
                        //通過反射的方法給屬性賦值
                        setSex.invoke(methodResult,"男");
                    } else {
                        setSex.invoke(methodResult,"女");
                    }
                } else {
                    setSex.invoke(methodResult,"未知");
                }
            } else {
                setSex.invoke(methodResult,sexResult);
            }
        } else {
            System.out.println("返回值為空!");
        }
    }
}

測(cè)試

請(qǐng)求報(bào)文

{
    "sid": 1
}

返回報(bào)文

{
    "sid": 1,
    "sname": "小明",
    "address": null,
    "identifyType": "01",
    "identifyNumber": "510123196908151288",
    "sex": "女"
}

假設(shè)場(chǎng)景2

在場(chǎng)景一的基礎(chǔ)上,我們又有了一個(gè)新的需求,為了方便展示,后端在返回identifyType=01的基礎(chǔ)上再返回一個(gè)證件類型的中文名稱。

處理邏輯2

添加一個(gè)注解,可以直接操作json,添加一個(gè)字段,返回證件的中文名稱。

實(shí)現(xiàn)邏輯2

添加注解IdentifyTypeChange,將使用此注解的參數(shù),在IdentifyTypeSerialize類中統(tǒng)一處理

@Inherited
@Documented
@Target({ElementType.FIELD})
@JsonSerialize(using = IdentifyTypeSerialize.class)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
public @interface IdentifyTypeChange {
    String identifyType() default "";
}

定義IdentifyTypeSerialize類,繼承JsonSerializer,并實(shí)現(xiàn)接口ContextualSerializer,在serialize中通過jsonGenerator.writeStringField方法直接添加一個(gè)參數(shù),并賦值

public class IdentifyTypeSerialize<T> extends JsonSerializer<T> implements ContextualSerializer {

    private static Map<String,String> identifyTypeMap = new HashMap<>();

    static {
        //定義常用的證件類型,或者通過數(shù)據(jù)庫(kù)查詢
        identifyTypeMap.put("01","身份證");
    }

    private String fieldName = "";

    //無參構(gòu)造方法必須要有,否則報(bào)錯(cuò)
    private IdentifyTypeSerialize() {}

    public IdentifyTypeSerialize(String fieldName) {
        this.fieldName = fieldName;
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        IdentifyTypeChange identifyTypeChange = beanProperty.getAnnotation(IdentifyTypeChange.class);
        if (Objects.nonNull(identifyTypeChange) && Objects.equals(String.class,beanProperty.getType().getRawClass())) {
            //拿到注解下面的參數(shù)名,并且賦值給fieldName,serialize方法會(huì)用到
            return new IdentifyTypeSerialize(beanProperty.getName());
        }
        return null;
    }

    @Override
    public void serialize(T value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        //如果原參數(shù)的值為空,那么還是寫回null
        if (Objects.isNull(value)) {
            jsonGenerator.writeNull();
            return;
        }
        //value注解下的參數(shù)的值
        String valueStr = value.toString();
        if (StringUtils.isBlank(valueStr)) {
            //將原參數(shù)值寫回,如果不寫回,原有identifyType的值將會(huì)為空
            jsonGenerator.writeString(valueStr);
            return;
        }
        if (StringUtils.isNotBlank(this.fieldName)) {
            //根據(jù)參數(shù)值獲取對(duì)應(yīng)的證件名字,然后再添加一個(gè)字段并賦值
            String identifyTypeName = identifyTypeMap.get(valueStr);
            if (StringUtils.isNotBlank(identifyTypeName)) {
                //這里寫注解下參數(shù)的值,也可以直接在這里修改注解下參數(shù)的值,例如現(xiàn)在identifyType的值為01,可以在后面直接加上身份證,就是:valueStr + identifyTypeName
                jsonGenerator.writeString(valueStr);
                //根據(jù)上面拿到的注解下參數(shù)名,添加一個(gè)反參
                jsonGenerator.writeStringField(this.fieldName + "Name", identifyTypeName);
                return;
            }
        } else {
            jsonGenerator.writeString(valueStr);
        }

    }
}

測(cè)試

請(qǐng)求報(bào)文

{
    "sid": 1
}

返回報(bào)文

{
    "sid": 1,
    "sname": "小明",
    "address": null,
    "identifyType": "01",
    "identifyTypeName": "身份證",
    "identifyNumber": "510123196908151288",
    "sex": "女"
}

總結(jié)

通過以上兩種方式,即可實(shí)現(xiàn)通過注解來處理結(jié)果,可以解決大多數(shù)問題。文章來源地址http://www.zghlxwxcb.cn/news/detail-627357.html

到了這里,關(guān)于Java AOP 通過注解實(shí)現(xiàn)切面及通過注解改變返回值的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(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)文章

  • 注解 + spring aop切面+ SpringEl

    2024年02月09日
    瀏覽(27)
  • Java Spring 通過 AOP 實(shí)現(xiàn)方法參數(shù)的重新賦值、修改方法參數(shù)的取值

    Java Spring 通過 AOP 實(shí)現(xiàn)方法參數(shù)的重新賦值、修改方法參數(shù)的取值

    我創(chuàng)建的項(xiàng)目項(xiàng)目為 SpringBoot 項(xiàng)目 這里以對(duì)前端傳遞過來的加密數(shù)據(jù)進(jìn)行解密為例 注解 控制器方法 方式一:通過環(huán)繞通知實(shí)現(xiàn) [個(gè)人比較推薦] 方式二:通過前置通知 + 反射實(shí)現(xiàn) Java ReflectUtil 反射相關(guān)的工具類 由于 JDK 8 中有關(guān)反射相關(guān)的功能自從 JDK 9 開始就已經(jīng)被限制了

    2024年02月04日
    瀏覽(26)
  • 【Spring】javaBean、依賴注入、面向切面AOP、使用注解開發(fā)

    【Spring】javaBean、依賴注入、面向切面AOP、使用注解開發(fā)

    有一定規(guī)范的Java實(shí)體類,類內(nèi)提供了一些公共方法以便外界對(duì)該對(duì)象的內(nèi)部屬性進(jìn)行操作 所有屬性都是private,所有的屬性都可以通過get/set方法進(jìn)行訪問,同時(shí)還需要有一個(gè)無參構(gòu)造(默認(rèn)就有) 高內(nèi)聚,低耦合是現(xiàn)代軟件的開發(fā)的設(shè)計(jì)模式 之前編寫的圖書管理系統(tǒng)具有高

    2024年02月08日
    瀏覽(57)
  • 如何將重復(fù)方法封裝為Aop切面并結(jié)合注解使用

    如何將重復(fù)方法封裝為Aop切面并結(jié)合注解使用

    首先要導(dǎo)入依賴 編寫注解 編寫Aop 方法上添加注解 ? 然后測(cè)試就發(fā)現(xiàn)添加代碼的方法都可以防止重復(fù)提交了??!

    2024年02月02日
    瀏覽(20)
  • JAVA:使用 Spring AOP 實(shí)現(xiàn)面向切面編程

    JAVA:使用 Spring AOP 實(shí)現(xiàn)面向切面編程

    1、簡(jiǎn)述 在現(xiàn)代的軟件開發(fā)中,面向切面編程(AOP)是一種重要的編程范式,它允許我們將橫切關(guān)注點(diǎn)(如日志記錄、性能監(jiān)控、事務(wù)管理等)從應(yīng)用程序的核心業(yè)務(wù)邏輯中分離出來,以提高代碼的模塊化和可維護(hù)性。Spring 框架提供了強(qiáng)大的 AOP 支持,使得我們可以輕松地實(shí)

    2024年04月13日
    瀏覽(31)
  • Spring Boot 自定義注解,AOP 切面統(tǒng)一打印出入?yún)⒄?qǐng)求日志

    Spring Boot 自定義注解,AOP 切面統(tǒng)一打印出入?yún)⒄?qǐng)求日志

    今天主要說說如何通過自定義注解的方式,在 Spring Boot 中來實(shí)現(xiàn) AOP 切面統(tǒng)一打印出入?yún)⑷罩?。小伙伴們可以收藏一波?廢話不多說,進(jìn)入正題! 在看看實(shí)現(xiàn)方法之前,我們先看下切面日志輸出效果咋樣: 從上圖中可以看到,每個(gè)對(duì)于每個(gè)請(qǐng)求,開始與結(jié)束一目了然,并且

    2024年02月08日
    瀏覽(22)
  • spring-自定義AOP面向切面注解--統(tǒng)一切面處理-登陸信息采集

    spring-自定義AOP面向切面注解--統(tǒng)一切面處理-登陸信息采集

    2023華為OD統(tǒng)一考試(A+B卷)題庫(kù)清單-帶答案(持續(xù)更新)or2023年華為OD真題機(jī)考題庫(kù)大全-帶答案(持續(xù)更新) 1. 先寫一個(gè)登陸記錄注解(//記錄:XXX時(shí)間,XXX姓名,XX系統(tǒng),登錄成功) 2. 寫一個(gè)切面對(duì)注解進(jìn)行處理(業(yè)務(wù)邏輯處理,記錄登陸的信息) 3.寫一個(gè)登錄的控制類,

    2024年02月13日
    瀏覽(17)
  • 【Spring】使用aop切面編程時(shí)要給那些類加注解

    【Spring】使用aop切面編程時(shí)要給那些類加注解

    ??歡迎來到@邊境矢夢(mèng)°的csdn博文?? ???本文主要梳理?Spring?中使用aop切面編程時(shí)要給那些類加注解??? ??我是邊境矢夢(mèng)°,一個(gè)正在為秋招和算法競(jìng)賽做準(zhǔn)備的學(xué)生?? ??喜歡的朋友可以關(guān)注一下 ?????? ,下次更新不迷路?? Ps: 月亮越亮說明知識(shí)點(diǎn)越重要 (重要性或者

    2024年02月07日
    瀏覽(22)
  • 【Spring進(jìn)階系列丨第十篇】基于注解的面向切面編程(AOP)詳解

    【Spring進(jìn)階系列丨第十篇】基于注解的面向切面編程(AOP)詳解

    ? 注意,該類的兩個(gè)細(xì)節(jié): a、@Component注解向容器中注冊(cè)一個(gè)Bean。 b、@Aspect注解表示這個(gè)是一個(gè)切面類。 c、@Before注解表示的是這個(gè)是前置增強(qiáng)/前置通知。 ? 注意:對(duì)于業(yè)務(wù)Bean,我們也需要通過@Service注解來向容器中注冊(cè)。 ? 問題:我們看到對(duì)于切面類中定義的通知,有

    2024年04月23日
    瀏覽(29)
  • Spring5框架——AOP操作:通過Aspectj注解方式和配置文件方式來實(shí)現(xiàn)

    Spring5框架——AOP操作:通過Aspectj注解方式和配置文件方式來實(shí)現(xiàn)

    o((⊙﹏⊙))o. ** 之前的博客介紹了什么是AOP,以及AOP的底層原理,AOP主要是在原本的基礎(chǔ)上添加一些之外的功能但是添加的功能是不會(huì)修改原定的代碼,接下來為你介紹的是Aspectj注解,Spring 框架一般都是基于 AspectJ 實(shí)現(xiàn) AOP 操作。AspectJ 不是 Spring 組成部分,獨(dú)立 AOP 框架,一

    2024年02月16日
    瀏覽(20)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包