Java动态代理(一)
好久没有动笔了,最近想巩固一下自己的基础知识,最近听到一同事问为什么JDK动态代理不能代理类,一听感觉懵逼呀!自己好像也不能很好的描述出来,所以想用2篇文章来复习一下动态代理知识;
一、什么是静态代理?什么是动态代理?
静态代理:
静态代理是在写代码中就把各个代理关系给理清了,在编译期就确定了类之间的关系;
动态代理:
在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能;
二、为什么要使用代理?
兄弟,你打方法的出入参的代码可以推一个房子了吧。使用代理可以将代码解耦,很多时候我们只要去关注我们最核心的实现,一些其他方面我可以交给代理去实现。最好的说明就是我们日常的AOP日志了,就是靠代理实现的。
三、简单的代理实现
静态代理的简单实现代码参考我前面的代理模式的代码:
今天我们先要写一下动态代理的简单代码:
InvocationHandler
InvocationHandler是JDK中提供的专门用于实现基于接口的动态代理的接口,主要用于进行方法调用模块,而代理类和实例的生成需要借助Proxy类完成。每个代理类的实例的调用处理器都是实现该接口实现的,而且是必备的,即每个动态代理实例的实现都必须拥有实现该接口的调用处理器,也可以这么说,每个动态代理实例都对应一个调用处理器。这里要区分两个概念,代理类和代理实例,调用处理器是在创建代理实例的时候才与其关联起来的,所以它与代理实例是一一对应的,而不是代理类。
Proxy
Proxy类是JDK提供的用于生成动态代理类和其实例的类。我们可以通过Proxy中的静态方法getProxyClass来生成代理类,需要的参数为类加载器和接口列表(数组),然后再通过反射调用代理类的构造器来生成代理实例,需要以一个InvocationHandler作为参数(体现出方法调用是与实例相关的,而非类)。
了解了上面我们开始写代码实现:
先写一个接口UserService,里面包含一个根据id查询用户名的方法,我们在这个查询方法的前后打印出出入参
- 1 package com.roc.study.proxy;
- 2
- 3 /**
- 4 * <code>用户service</code>
- 5 * <b>Note</b>
- 6 *
- 7 * @author liaowp
- 8 * @see
- 9 * @since 2018/5/14
- 10 */
- 11
- 12 public interface UserService {
- 13
- 14 /**
- 15 * 查询用户名称
- 16 * @param id
- 17 * @return
- 18 */
- 19 String getUserName(Integer id);
- 20
- 21 }
- 1 package com.roc.study.proxy;
- 2
- 3 /**
- 4 * <code>用户service实现类</code>
- 5 * <b>Note</b>
- 6 *
- 7 * @author liaowp
- 8 * @see
- 9 * @since 2018/5/14
- 10 */
- 11 public class UserServiceImpl implements UserService {
- 12
- 13 /**
- 14 * 查询用户名称
- 15 *
- 16 * @return
- 17 */
- 18 @Override
- 19 public String getUserName(Integer id) {
- 20 System.out.println("liaowp");
- 21 return "liaowp";
- 22 }
- 23 }
- 1 package com.roc.study.proxy;
- 2
- 3 import java.lang.reflect.InvocationHandler;
- 4 import java.lang.reflect.Method;
- 5 import java.lang.reflect.Proxy;
- 6
- 7 /**
- 8 * <code>用户代理类</code>
- 9 * <b>Note</b>
- 10 *
- 11 * @author liaowp
- 12 * @see
- 13 * @since 2018/5/14
- 14 */
- 15
- 16 public class UserInvocationHandler implements InvocationHandler {
- 17
- 18 private Object target;
- 19
- 20 public UserInvocationHandler(Object target) {
- 21 this.target = target;
- 22 }
- 23
- 24 /**
- 25 * 在代理实例上处理方法调用并返回结果。
- 26 * 当在与其关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
- 27 * @param proxy 我们所代理的那个真实对象
- 28 * @param method 方法
- 29 * @param args 入参
- 30 * @return
- 31 * @throws Throwable
- 32 */
- 33 @Override
- 34 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- 35 System.out.println("入参args->" + args);
- 36 // 执行目标对象的方法
- 37 Object result = method.invoke(target, args);
- 38 System.out.println("出参args->"+result.toString());
- 39 return result;
- 40 }
- 41
- 42 /**
- 43 * 获取目标对象的代理对象
- 44 * @return 代理对象
- 45 */
- 46 public Object getProxy() {
- 47 return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
- 48 target.getClass().getInterfaces(), this);
- 49 }
- 50
- 51 }
- package com.roc.study.proxy;
- /**
- * <code>代理测试类</code>
- * <b>Note</b>
- *
- * @author liaowp
- * @see
- * @since 2018/5/14
- */
- public class ProxyTest {
- public static void main(String[] args) {
- UserService userService = new UserServiceImpl();
- UserInvocationHandler userInvocationHandler = new UserInvocationHandler(userService);
- // 根据目标对象生成代理对象
- UserService proxy = (UserService) userInvocationHandler.getProxy();
- // 调用代理对象的方法
- proxy.getUserName(1);
- }
- }
运行结果:
入参args->[Ljava.lang.Object;@5cad8086
liaowp
出参args->liaowp
Process finished with exit code 0
Java动态代理(一)的更多相关文章
- Java 动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- Java动态代理全面分析
代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1 主题:规定代理类和真实对象共同对外暴露的接口: 2 代理类:专门代理真实对象的类: 3 ...
- JAVA动态代理模式(从现实生活角度理解代码原理)
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...
- Java 动态代理作用是什么?
Java 动态代理作用是什么? 1 条评论 分享 默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...
- java动态代理原理
我们经常会用到Java的动态代理技术, 虽然会使用, 但是自己对其中的原理却不是很了解.比如代理对象是如何产生的, InvocationHandler的invoke方法是如何调用的?今天就来深究下Ja ...
- java 动态代理示例,带主要注释
Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...
- java动态代理浅析
最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 于是想起了java的动态代理,然后就有了这篇文章 ...
- Java 动态代理
被代理的接口特点: 1. 不能有重复的接口,以避免动态代理类代码生成时的编译错误. 2. 这些接口对于类装载器必须可见,否则类装载器将无法链接它们,将会导致类定义失败. 3. 需被代理的所有非 pub ...
- [转]java动态代理(JDK和cglib)
转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...
- java动态代理模式
java动态代理机制详解 Spring的核心AOP的原理就是java的动态代理机制. 在java的动态代理机制中,有两个重要的类或接口: 1.InvocationHandler(Interface): ...
随机推荐
- SpriteBuilder改变布局后App运行出错代码排查
原来整个关卡场景放在GameScene.ccb中,后来觉得移到专门的Level.ccb比较好. 移动过后编译运行,只要移动Player的胳膊发射子弹时,Xcode报错: g due to Chipmu ...
- Ubuntu 14 安装MySQL指南
ubuntu 14 安装MySQL指南安装MySQLsudo apt-get install mysql-server这个应该很简单了,而且我觉得大家在安装方面也没什么太大问题,所以也就不多说了,下面 ...
- Android SDK工具(谷歌提供的16个工具)简介
Android SDK包含了许多可以帮助你开发Android平台应用的工具.这些工具分为两类:一是SDK工具:而是平台工具.SDK工具独立于平台,任何开发Android应用的平台都需要配置.平台工具是 ...
- 【66】Scanner类用法详解
Scanner是新增的一个简易文本扫描器,在 JDK 5.0之前,是没有的. public final class Scanner extends Object implements Iterator ...
- 对MBProgressHUD第三方进行源码分析
GitHub源码地址,及时更新:iOS-Source-Code-Analyze MBProgressHUD是一个为iOS app添加透明浮层 HUD 的第三方框架.作为一个 UI 层面的框架,它的实现 ...
- CImage 对话框初始化时候显示透明 PNG
使用CImage的时候,发现显示出来的并不是透明背景的图片,而是白色背景的图片. 后发现原因如下: PNG图片的透明背景总是一片白色,后来才发现这其实是微软GDI+的设计问题,PNG图片是ARGB,使 ...
- Spring的声明式事务管理
在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例外(RunTimeExcep ...
- Treemap 有序的hashmap。用于排序
TreeMap:有固定顺序的hashmap.在需要排序的Map时候才用TreeMap. Map.在数组中我们是通过数组下标来对其内容索引的,键值对. HashMap HashMap 用哈希码快速定位一 ...
- 获取list,有内容就赋值,根据ID显现NAME,没有显现list
function onTOWN() { var town=mini.get("TOWN_ID"); var town_id =town.getValue(); $.ajax({ u ...
- Js 实现自定义事件
var Event = { on: function (eventName, callback) { if (!this[eventName]) { this[eventName] = []; } t ...