注解+代理 模仿 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=强哥
阅读全文
1 0
- 注解+代理 模仿 Retrofit 传参
- Retrofit注解
- 动态代理获取方法上的注解(Retrofit框架必备内容)
- Retrofit之Query注解
- Retrofit 注解字段说明
- Retrofit 注解 详解
- retrofit 注解含义
- Retrofit的注解使用
- Retrofit新手常用注解
- retrofit 注解学习
- Retrofit 注解使用
- Retrofit的动态代理
- 代理、注解
- 模仿Spring实现注解注入
- 模仿JDK实现动态代理
- Retrofit 2.0 个注解详解
- Retrofit常见注解全解析
- Retrofit常见注解全解析
- Windwos下安装CYGwin及任务计划使用方法
- 《编写可维护的JavaScript》读书笔记(2)---注释
- 伺服电机抖动原因分析
- POJ
- Dubbo&ZK分布式服务化改造(四)——Dubbo多注册中心 & 服务迁移
- 注解+代理 模仿 Retrofit 传参
- 书籍阅读
- 编程题赏析4之微信红包
- 【JS】:JS实现判断输入字符串是否合乎邮箱格式
- Wex5 this.comp().val() of undefined 解决方法
- linux squid 普通代理 透明代理 反向代理
- perl 处理文件路径的一些模块
- 有关LateX概念总结
- 【php+centos7+pgsql】centos下面配置php访问postgresql的方式