Java通过注解实现一个接口--利用反射与代理

概述

传统实现接口的方式需要implement才行,通过注解实现一个接口可以减轻每次都要implement的繁琐。本文实现一个Demo来展示如何通过注解实现一个接口。

Code

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 利用反射与代理实现一个利用注解实现接口的功能,作为展示,只支持函数接口,即接口中只有一个函数,且只支持一个接口。
 */
class Scratch {
    public static void main(String[] args) throws Exception {
        Lego lego = new Lego();
        Playable playable = buildInterfaceClass(lego, Playable.class, Play.class);
        playable.play();
    }

    /**
     *
     * @param object 有相应注解标记相应函数的类的对象
     * @param interfaceClazz 待实现接口的Class
     * @param annotationClazz 注解的Class
     * @param <T> 接口类型
     * @return 实现了接口的代理类对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T buildInterfaceClass(Object object, Class<T> interfaceClazz, Class annotationClazz) {
        return (T) Proxy.newProxyInstance(interfaceClazz.getClassLoader(), new Class[]{interfaceClazz}, new InterfaceHandler(object, annotationClazz));
    }

    /**
     * 找出特定类上被特定注解标记的方法
     * @param objectClass 类的Class
     * @param annotationClass 注解的Class
     * @return 被annotationClass标记的方法
     * @throws Exception 没有方法上面有annotationClass的注解
     */
    public static Method getInterfaceMethod(Class<?> objectClass, Class<? extends Annotation> annotationClass) throws Exception {
        Method[] declaredMethods = objectClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            Annotation[] declaredAnnotations = declaredMethod.getDeclaredAnnotations();
            for (Annotation declaredAnnotation : declaredAnnotations) {
                if (declaredAnnotation.annotationType().equals(annotationClass)) {
                    return declaredMethod;
                }
            }
        }

        throw new Exception("没有含有 " + annotationClass.getName() + " 注解的方法");
    }

    /**
     * 对代理类上相应的函数调用转化为被特定注解标记的函数调用
     */
    private static class InterfaceHandler implements InvocationHandler {
        private Object object;
        private Class annotationClazz;

        public InterfaceHandler(Object object, Class annotationClazz) {
            this.object = object;
            this.annotationClazz = annotationClazz;
        }


        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().toLowerCase().endsWith(annotationClazz.getSimpleName().toLowerCase())) {
                Method interfaceMethod = getInterfaceMethod(object.getClass(), annotationClazz);
                return interfaceMethod.invoke(object, args);
            }
            throw new Exception("未实现函数");
        }
    }

}


/**
 * 待实现的接口
 */
interface Playable {
    void play();
}

/**
 * 在方法上加上Play注解即可实现Playable中的Play方法
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Play {
}

/**
 * 有注解标记函数的类,即我们希望通过注解实现接口的类
 */
class Lego {

    @Play
    void foo() {
        System.out.println("I can play");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值