注解+代理 模仿 Retrofit 传参

来源:互联网 发布:星星网络星盘查询 编辑:程序博客网 时间:2024/05/19 14:01

前几天学习了一下注解和代理。这里记录一下使用自定义注解 + 动态代理,来模仿 Retrofit 的传参方式。

注解

Java 元注解有四种,这是系统定义的用于定义注解时,区分他们的不同作用。

  • @Target
  • @Retention
  • @Documented
  • @Inherited

@Target

用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值类型有:

ElemenetType.CONSTRUCTOR 构造器声明ElemenetType.FIELD 域声明,成员变量、对象、属性(包括 enum 实例) ElemenetType.LOCAL_VARIABLE 局部变量声明 ElemenetType.METHOD 方法声明 ElemenetType.PACKAGE 包声明 ElemenetType.PARAMETER 参数声明 ElemenetType.TYPE 类,接口(包括注解类型)或enum声明

以上有些部分没有领悟到用法。。下面用到的也就 PARAMETER , METHOD 两种。

@Retention

定义了该Annotation被保留的时间长短.
取值类型:

RetentionPolicy.SOURCE 注解将被编译器丢弃 ,在源文件中有效(即源文件保留)RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 。在class文件中有效(即class保留)RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。在运行时有效(即运行时保留)

一般常用的是 RUNTIME 类型

@Documented

用于描述其它类型的 Annotation 应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

@Inherited

指示允许子类继承父类中的注解,用于该类的子类。

代理

代理模式其实也挺简单,也就是一种委托机制,真是对象将方法的执行委托给代理对象,而且委托的干净利落。所以,代理模式也称之为委托模式,

先定义一个接口(抽象主题类):

public interface ISubject {    void start();    void pause();    void stop();    String result();}

然后是一个真实处理类(真实主题类):

public class RealSubject implements ISubject {    @Override    public void start() {        System.out.println("this is real subject start()");    }    @Override    public void pause() {        System.out.println("this is real subject pause()");    }    @Override    public void stop() {        System.out.println("this is real subject stop()");    }    @Override    public String result() {        return "this is real subject result String ";    }}

静态代理

创建静态代理类:

public class ProxySubject implements ISubject {    private ISubject subject;    public ProxySubject(ISubject subject) {        this.subject = subject;    }    @Override    public void start() {        subject.start();    }    @Override    public void pause() {        subject.pause();    }    @Override    public void stop() {        subject.stop();    }    @Override    public String result() {        return subject.result();    }}

执行代码 :

public static void main(String[] args) {        // 测试静态代理        RealSubject realSubject = new RealSubject();        ProxySubject proxySubject = new ProxySubject(realSubject);        proxySubject.start();        proxySubject.pause();        proxySubject.stop();        System.out.println("result " + proxySubject.result());}

执行结果:

this is real subject start()this is real subject pause()this is real subject stop()result this is real subject result String 

动态代理

Java 提供了一个便捷的动态代理接口。InvocationHandler,使用时需要实现该接口,并且重写 invoke 方法。
InvocationHandler 实现类:

public class DynamicProxy implements InvocationHandler {    private Object object;    public DynamicProxy(Object object) {        this.object = object;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        String name = method.getDeclaringClass().getName();//        System.out.println(name);        return method.invoke(object, args);    }}

调用:

public static void main(String[] args) {        // 测试动态代理        RealSubject realSubject = new RealSubject();        DynamicProxy dynamicProxy = new DynamicProxy(realSubject);        ISubject subject = (ISubject) Proxy.newProxyInstance(ISubject.class.getClassLoader(), new Class[]{ISubject.class}, dynamicProxy);        subject.start();        subject.pause();        subject.stop();        System.out.println("result " + subject.result());    }

invoke 方法当 subject 中方法被调用时,才会执行。
执行结果和静态代理的结果是一样的,这里就不重复贴出。

模仿 Retrofit 传参

  • 定义注解:
@Target(ElementType.METHOD) // 方法注解@Retention(RetentionPolicy.RUNTIME)@interface Say {    String value() default "这是默认值";}@Target(ElementType.PARAMETER) //参数注解@Retention(RetentionPolicy.RUNTIME)@interface Query {    String value();}@Target(ElementType.PARAMETER)//参数注解@Retention(RetentionPolicy.RUNTIME)@interface Filed {    String value();}
  • 定义 InvocationHandler 实现类:
static class ProxyHandler implements InvocationHandler {        @Override        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//            Annotation[] deAn = method.getDeclaredAnnotations();//            for (int i = 0; i < deAn.length; i++) {//                Annotation an = deAn[i];//                if (Say.class.isInstance(an)) {//                    System.out.println(((Say) an).value());//                }//            }            Say say = method.getAnnotation(Say.class);            Annotation[][] param = method.getParameterAnnotations();  // 获取参数注解            String str = "?" + say.value();            for (int i = 0; i < param.length; i++) {                Annotation[] p = param[i];                for (int j = 0; j < p.length; j++) {                    Annotation a = p[j];                    if (Query.class.isInstance(a)) {                        Query query = (Query) a;                        str += "&" + ((Query) a).value() + "=" + args[i];                    } else if (Filed.class.isInstance(a)) {                        str += "@" + ((Filed) a).value() + "=" + args[i];                    }                }            }//            System.out.println(str);            return str;        }    }
  • 使用注解:
interface Subject {       @Say("方法")// 注解传参时, 默认键为 value,如果注解的参数 key 不是 value() 则需要写明[key]=""。       String getName(@Query("name") String name, @Filed("nick") String nick);   }
  • 最终调用:
 public static void main(String[] args) {        ProxyHandler handler = new ProxyHandler();        Subject s = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[]{Subject.class}, handler);        System.out.println(s.getName("发强", "强哥"));    }
  • 输出结果
?方法&name=发强@nick=强哥
原创粉丝点击