栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

案例:参数填写默认值【注解+JDK动态代理】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

案例:参数填写默认值【注解+JDK动态代理】

学如逆水行舟,不进则退~
今天记录一个小案例:当一个实例调用一个有参方法的时候,判断该参数是否为NULL,如果是NULL则给一个默认值。

1、定义一个校验是否为NULL并且给定默认值的参数

package com.dongzi;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CheckParam {

    
    boolean required() default false;

    
    String defaultValue() default "";
}

2、定义一个为实现一个代理的统一行为人接口

package com.dongzi;


public interface People {

    
    void say(String saySomething);
}

3、定义一个实现该行为方式的学生类

package com.dongzi;


public class Student implements People {

    @Override
    public void say(@CheckParam(required = true, defaultValue = "再见,小哥哥~~") String saySomething) {
        System.out.println("To Talk:" + saySomething);
    }
}

4、定义一个动态代理对象

package com.dongzi;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


public class PeopleInvocationHandlerImpl implements InvocationHandler {

    
    private final Object proxyObj;

    public PeopleInvocationHandlerImpl(Object proxyObj) {
        this.proxyObj = proxyObj;
    }

    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Class proxyObjClass = this.proxyObj.getClass();
        Method[] methods = proxyObjClass.getMethods();
        Method myMethod = null;
        for (Method m : methods) {
            if (m.getName().equals(method.getName())) {
                myMethod = m;
                break;
            }
        }
        if (myMethod != null) {
            
            Annotation[][] annotations = myMethod.getParameterAnnotations();
            if (annotations.length > 0) {
                for (int i = 0; i < annotations.length; i++) {
                    for (int j = 0; j < annotations[i].length; j++) {
                        Annotation anno = annotations[i][j];
                        if (anno instanceof CheckParam) {
                            // 参数检查的注解
                            if (((CheckParam) anno).required()) {
                                String defaultValue = ((CheckParam) anno).defaultValue();
                                // 对第i个参数并且符合参数检查的注解进行赋默认值
                                // TODO:这里需要注意一下问题,方便测试使用的String类型参数,如果多个参数的话,类型也要为String,其他类型没有考虑,否则会因为参数类型不一致而无法正常执行invoke方法
                                args[i] = (null == args[i] || "".equals(args[i])) ? defaultValue : args[i];
                            }
                            // TODO: 符合其他参数上的注解 if()
                        }
                    }
                }
            }
        }
        // 执行被代理类的方法
        // args参数类型必须全部匹配否则异常无法执行invoke反射到对应方法执行
        return method.invoke(this.proxyObj, args);
    }
}

5、主程序

package com.dongzi;

import java.lang.reflect.Proxy;


public class Main {


    public static void main(String[] args) {

        // 确定被代理的对象
        Student student = new Student();
        PeopleInvocationHandlerImpl handler = new PeopleInvocationHandlerImpl(student);
        
        People studentProxyObj = (People) Proxy.newProxyInstance(student.getClass().getClassLoader(), student.getClass().getInterfaces(), handler);

        // 被代理之后,执行方法
        studentProxyObj.say("你好,小哥哥~~"); // 输出:To Talk:你好,小哥哥~~
        studentProxyObj.say(null); // 输出结果:To Talk:再见,小哥哥~~
    }
}

6、执行结果

    两次调用say()方法的结果:第一次调用传入参数,参数正常打印;第二次传入NULL,正常来说会打印NULL值,而不是输出一段描述,但是因为加了注解并给定默认值,所以会打印出defaultValue的值,而并不是NULL。

附1:项目结构

附2:一些关于JDK动态代理和注解

  • Java Reflect - 利用反射获取方法参数上的注解
  • Java JDK 动态代理(AOP)使用及实现原理分析
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/933225.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号