案例:参数填写默认值【注解+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;
    }

    /**
     * @param proxy  代理类实例
     * @param method 代理方法
     * @param args   参数
     */
    @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[i][j]
                i: 参数列表中第i个参数
                j: 第i个参数中的第j个注解
             */
            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动态代理和注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白说(๑• . •๑)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值