好久没有动笔了,最近想巩固一下自己的基础知识,最近听到一同事问为什么JDK动态代理不能代理类,一听感觉懵逼呀!自己好像也不能很好的描述出来,所以想用2篇文章来复习一下动态代理知识;

一、什么是静态代理?什么是动态代理?  

  静态代理:
    静态代理是在写代码中就把各个代理关系给理清了,在编译期就确定了类之间的关系;
  动态代理:
    在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能;

二、为什么要使用代理?  

  兄弟,你打方法的出入参的代码可以推一个房子了吧。使用代理可以将代码解耦,很多时候我们只要去关注我们最核心的实现,一些其他方面我可以交给代理去实现。最好的说明就是我们日常的AOP日志了,就是靠代理实现的。

三、简单的代理实现  

  静态代理的简单实现代码参考我前面的代理模式的代码:
  今天我们先要写一下动态代理的简单代码:  

   InvocationHandler    

    InvocationHandler是JDK中提供的专门用于实现基于接口的动态代理的接口,主要用于进行方法调用模块,而代理类和实例的生成需要借助Proxy类完成。每个代理类的实例的调用处理器都是实现该接口实现的,而且是必备的,即每个动态代理实例的实现都必须拥有实现该接口的调用处理器,也可以这么说,每个动态代理实例都对应一个调用处理器。这里要区分两个概念,代理类和代理实例,调用处理器是在创建代理实例的时候才与其关联起来的,所以它与代理实例是一一对应的,而不是代理类。   

  Proxy    

    Proxy类是JDK提供的用于生成动态代理类和其实例的类。我们可以通过Proxy中的静态方法getProxyClass来生成代理类,需要的参数为类加载器和接口列表(数组),然后再通过反射调用代理类的构造器来生成代理实例,需要以一个InvocationHandler作为参数(体现出方法调用是与实例相关的,而非类)。
  了解了上面我们开始写代码实现:

  先写一个接口UserService,里面包含一个根据id查询用户名的方法,我们在这个查询方法的前后打印出出入参

  1. 1 package com.roc.study.proxy;
  2. 2
  3. 3 /**
  4. 4 * <code>用户service</code>
  5. 5 * <b>Note</b>
  6. 6 *
  7. 7 * @author liaowp
  8. 8 * @see
  9. 9 * @since 2018/5/14
  10. 10 */
  11. 11
  12. 12 public interface UserService {
  13. 13
  14. 14 /**
  15. 15 * 查询用户名称
  16. 16 * @param id
  17. 17 * @return
  18. 18 */
  19. 19 String getUserName(Integer id);
  20. 20
  21. 21 }
  1. 1 package com.roc.study.proxy;
  2. 2
  3. 3 /**
  4. 4 * <code>用户service实现类</code>
  5. 5 * <b>Note</b>
  6. 6 *
  7. 7 * @author liaowp
  8. 8 * @see
  9. 9 * @since 2018/5/14
  10. 10 */
  11. 11 public class UserServiceImpl implements UserService {
  12. 12
  13. 13 /**
  14. 14 * 查询用户名称
  15. 15 *
  16. 16 * @return
  17. 17 */
  18. 18 @Override
  19. 19 public String getUserName(Integer id) {
  20. 20 System.out.println("liaowp");
  21. 21 return "liaowp";
  22. 22 }
  23. 23 }
  1. 1 package com.roc.study.proxy;
  2. 2
  3. 3 import java.lang.reflect.InvocationHandler;
  4. 4 import java.lang.reflect.Method;
  5. 5 import java.lang.reflect.Proxy;
  6. 6
  7. 7 /**
  8. 8 * <code>用户代理类</code>
  9. 9 * <b>Note</b>
  10. 10 *
  11. 11 * @author liaowp
  12. 12 * @see
  13. 13 * @since 2018/5/14
  14. 14 */
  15. 15
  16. 16 public class UserInvocationHandler implements InvocationHandler {
  17. 17
  18. 18 private Object target;
  19. 19
  20. 20 public UserInvocationHandler(Object target) {
  21. 21 this.target = target;
  22. 22 }
  23. 23
  24. 24 /**
  25. 25 * 在代理实例上处理方法调用并返回结果。
  26. 26 * 当在与其关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
  27. 27 * @param proxy 我们所代理的那个真实对象
  28. 28 * @param method 方法
  29. 29 * @param args 入参
  30. 30 * @return
  31. 31 * @throws Throwable
  32. 32 */
  33. 33 @Override
  34. 34 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  35. 35 System.out.println("入参args->" + args);
  36. 36 // 执行目标对象的方法
  37. 37 Object result = method.invoke(target, args);
  38. 38 System.out.println("出参args->"+result.toString());
  39. 39 return result;
  40. 40 }
  41. 41
  42. 42 /**
  43. 43 * 获取目标对象的代理对象
  44. 44 * @return 代理对象
  45. 45 */
  46. 46 public Object getProxy() {
  47. 47 return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
  48. 48 target.getClass().getInterfaces(), this);
  49. 49 }
  50. 50
  51. 51 }
  1. package com.roc.study.proxy;
  2.  
  3. /**
  4. * <code>代理测试类</code>
  5. * <b>Note</b>
  6. *
  7. * @author liaowp
  8. * @see
  9. * @since 2018/5/14
  10. */
  11. public class ProxyTest {
  12.  
  13. public static void main(String[] args) {
  14. UserService userService = new UserServiceImpl();
  15. UserInvocationHandler userInvocationHandler = new UserInvocationHandler(userService);
  16. // 根据目标对象生成代理对象
  17. UserService proxy = (UserService) userInvocationHandler.getProxy();
  18. // 调用代理对象的方法
  19. proxy.getUserName(1);
  20. }
  21. }

运行结果:

入参args->[Ljava.lang.Object;@5cad8086
liaowp
出参args->liaowp

Process finished with exit code 0

Java动态代理(一)的更多相关文章

  1. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  2. Java动态代理全面分析

    代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1  主题:规定代理类和真实对象共同对外暴露的接口: 2  代理类:专门代理真实对象的类: 3 ...

  3. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  4. Java 动态代理作用是什么?

    Java 动态代理作用是什么?   1 条评论 分享   默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...

  5. java动态代理原理

    我们经常会用到Java的动态代理技术, 虽然会使用, 但是自己对其中的原理却不是很了解.比如代理对象是如何产生的, InvocationHandler的invoke方法是如何调用的?今天就来深究下Ja ...

  6. java 动态代理示例,带主要注释

    Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...

  7. java动态代理浅析

    最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 于是想起了java的动态代理,然后就有了这篇文章 ...

  8. Java 动态代理

    被代理的接口特点: 1. 不能有重复的接口,以避免动态代理类代码生成时的编译错误. 2. 这些接口对于类装载器必须可见,否则类装载器将无法链接它们,将会导致类定义失败. 3. 需被代理的所有非 pub ...

  9. [转]java动态代理(JDK和cglib)

    转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...

  10. java动态代理模式

    java动态代理机制详解 Spring的核心AOP的原理就是java的动态代理机制. 在java的动态代理机制中,有两个重要的类或接口: 1.InvocationHandler(Interface): ...

随机推荐

  1. SpriteBuilder改变布局后App运行出错代码排查

    原来整个关卡场景放在GameScene.ccb中,后来觉得移到专门的Level.ccb比较好. 移动过后编译运行,只要移动Player的胳膊发射子弹时,Xcode报错: g due to Chipmu ...

  2. Ubuntu 14 安装MySQL指南

    ubuntu 14 安装MySQL指南安装MySQLsudo apt-get install mysql-server这个应该很简单了,而且我觉得大家在安装方面也没什么太大问题,所以也就不多说了,下面 ...

  3. Android SDK工具(谷歌提供的16个工具)简介

    Android SDK包含了许多可以帮助你开发Android平台应用的工具.这些工具分为两类:一是SDK工具:而是平台工具.SDK工具独立于平台,任何开发Android应用的平台都需要配置.平台工具是 ...

  4. 【66】Scanner类用法详解

    Scanner是新增的一个简易文本扫描器,在 JDK 5.0之前,是没有的. public final class Scanner extends Object implements Iterator ...

  5. 对MBProgressHUD第三方进行源码分析

    GitHub源码地址,及时更新:iOS-Source-Code-Analyze MBProgressHUD是一个为iOS app添加透明浮层 HUD 的第三方框架.作为一个 UI 层面的框架,它的实现 ...

  6. CImage 对话框初始化时候显示透明 PNG

    使用CImage的时候,发现显示出来的并不是透明背景的图片,而是白色背景的图片. 后发现原因如下: PNG图片的透明背景总是一片白色,后来才发现这其实是微软GDI+的设计问题,PNG图片是ARGB,使 ...

  7. Spring的声明式事务管理

    在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例外(RunTimeExcep ...

  8. Treemap 有序的hashmap。用于排序

    TreeMap:有固定顺序的hashmap.在需要排序的Map时候才用TreeMap. Map.在数组中我们是通过数组下标来对其内容索引的,键值对. HashMap HashMap 用哈希码快速定位一 ...

  9. 获取list,有内容就赋值,根据ID显现NAME,没有显现list

    function onTOWN() { var town=mini.get("TOWN_ID"); var town_id =town.getValue(); $.ajax({ u ...

  10. Js 实现自定义事件

    var Event = { on: function (eventName, callback) { if (!this[eventName]) { this[eventName] = []; } t ...