先来一个InvocationHandler示例,InvocationHandler类的作用是:对原始对象的方法做一个拦截。

package com.zhang;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; interface HelloSerivce {
void sayHello();
void sayHi();
} interface FuckService {
void fuck();
} class HelloServiceImpl implements HelloSerivce {
@Override
public void sayHello() {
System.out.println("hello zhang");
} @Override
public void sayHi() {
System.out.println("hi zhang");
}
} public class InvocationHandler_Test {
public static void main(String[] args) {
class MyInvocationHandler implements InvocationHandler {
private Object obj;
public MyInvocationHandler(Object obj) {
this.obj = obj;
} //拦截方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ("sayHello".equals(method.getName())) {
System.out.println("拦截sayHello");
} else if("sayHi".equals(method.getName())) {
System.out.println("拦截sayHi");
}
//调用原始方法
method.invoke(obj, args);
return null;
} @Override
public String toString() {
return "MyInvocationHandler:" + System.currentTimeMillis();
}
} HelloSerivce helloSerivceImpl = new HelloServiceImpl();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(helloSerivceImpl);
//生成代理
Class<?>[] src = HelloServiceImpl.class.getInterfaces();
Class<?>[] dest = new Class<?>[src.length + 1];
System.arraycopy(src, 0, dest, 0, src.length);
dest[src.length] = FuckService.class; HelloSerivce proxyInstance = (HelloSerivce)Proxy.newProxyInstance(HelloServiceImpl.class.getClassLoader(),
dest, myInvocationHandler);
proxyInstance.sayHello();
proxyInstance.sayHi(); System.out.println(proxyInstance instanceof FuckService);
FuckService fService = (FuckService)proxyInstance;
//报错
fService.fuck();
}
}

dubbo consumer的InvokerInvocationHandler实现了InvocationHandler接口,拦截的是MockClusterInvoker对象的方法,这是jdk动态代理。

public class InvokerInvocationHandler implements InvocationHandler {
private final Invoker<?> invoker;
public InvokerInvocationHandler(Invoker<?> handler){
this.invoker = handler;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
//如果是Object的方法,直接调用原生对象的方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
//下面的判断其实是冗余的
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
//剩下的就需要发送请求给provider了
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}

比较一下jdk和javassist动态代理:

//JdkProxyFactory
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
interfaces, new InvokerInvocationHandler(invoker));
}
//JavassistProxyFactory
@SuppressWarnings("unchecked")
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}

存在HelloService接口:

public interface HelloService {
String sayHello();
}

Javassist为它动态生成的类代码大致如下:

class com.alibaba.dubbo.common.bytecode.proxy0 implements
com.alibaba.dubbo.rpc.service.EchoService, com.zhang.HelloService {
public <init>(java.lang.reflect.InvocationHandler arg0){
handler=$1;
}
public static java.lang.reflect.Method[] methods;
private java.lang.reflect.InvocationHandler handler; public java.lang.String sayHello(){
Object[] args = new Object[0];
//handler是InvokerInvocationHandler对象
Object ret = handler.invoke(this, methods[0], args);
return (java.lang.String)ret;
}
public java.lang.Object $echo(java.lang.Object arg0){
Object[] args = new Object[1];
args[0] = ($w)$1;
Object ret = handler.invoke(this, methods[1], args);
return (java.lang.Object)ret;
}
}

从上面能看出来:Javassist动态生成的类直接调用InvocationHandler,不是通过代理调用的。

javassist和jdk动态代理的更多相关文章

  1. JDK动态代理与Cglib库

    JDK动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在 ...

  2. AOP的底层实现:JDK动态代理与Cglib动态代理

    转载自 https://www.cnblogs.com/ltfxy/p/9872870.html SpringAOP底层的实现原理: JDK动态代理:只能对实现了接口的类产生代理.(实现接口默认JDK ...

  3. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(3):常用动态代理之JDK动态代理、CGLIB动态代理

    一.动态代理的理解 动态代理的意义在于生成一个占位(又称代理对象),来代理真实对象,从而控制真实对象的访问.        先来谈谈什么是代理模式.        假设这样一个场景:你的公司是一家软件 ...

  4. java学习笔记(中级篇)—JDK动态代理

    一.什么是代理模式 相信大家都知道代理商这个概念,在商业中,代理商无处不在.假设你要去买东西,你不可能去找真正的厂家去买,也不可能直接跟厂家提出需求,代理商就是这中间的一桥梁,连接买家和厂商.你要买或 ...

  5. 动态代理模式——JDK动态代理

    今天,我就来讲一下动态代理的设计模式. 动态代理的意义在于生成一个代理对象,来代理真实对象,从而控制真实对象的访问.操作动态代理需要两个步骤:一.代理对象和真实对象建立代理关系.二.实现代理对象的代理 ...

  6. 浅谈Spring中JDK动态代理与CGLIB动态代理

    前言Spring是Java程序员基本不可能绕开的一个框架,它的核心思想是IOC(控制反转)和AOP(面向切面编程).在Spring中这两个核心思想都是基于设计模式实现的,IOC思想的实现基于工厂模式, ...

  7. JDK 动态代理的实现

    JDK 动态代理的实现 虽然在常用的 Java 框架(Spring.MyBaits 等)中,经常见到 JDK 动态代理的使用,也知道了怎么去写一个 JDK 动态代理的 Demo,但是并不清楚实现原理. ...

  8. JDK动态代理

    一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...

  9. 静态代理和利用反射形成的动态代理(JDK动态代理)

    代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 静态代理 1.新建 ...

随机推荐

  1. python模块-json、pickle、shelve

    json模块 用于文件处理时其他数据类型与js字符串之间转换.在将其他数据类型转换为js字符串时(dump方法),首先将前者内部所有的单引号变为双引号,再整体加上引号(单或双)转换为js字符串:再使用 ...

  2. python监控端口脚本[jkport1.0.py]

    此脚本根据端口判断进程是否存活, 如果有指定的端口就证明进程是没问题的, 如果检测不到端口就是说业务进程已经挂掉了, 此时自动重启程序, 不多说下面请看脚本 创建脚本 我这里模拟的是nginx, 监控 ...

  3. TI 实时操作系统SYS/BIOS使用总结

    1:概述: SYS/BIOS 是一个可扩展的实时的操作系统.具有非常快速的响应时间(在中断和任务切换时达到较短的延迟),响应时间的确定性,强壮的抢占系统,优化的内存分配和堆栈管理(尽量少的消耗和碎片) ...

  4. 利用.bat(批处理)来删除KEIL编译生成的无用文件

    新建一个.txt文件. 在里面输入如下内容: del *.bak /s del *.ddk /s del *.edk /s del *.lst /s del *.lnp /s del *.mpf /s ...

  5. static理解

    static 修饰的变量称为类变量或全局变量或成员变量,在类被加载的时候成员变量即被初始化,与类关联,只要类存在,static变量就存在. 一个static变量单独划分一块存储空间,不与具体的对象绑定 ...

  6. C# string字节数组转换

    string转byte[]:byte[] byteArray = System.Text.Encoding.Default.GetBytes ( str ); byte[]转string:string ...

  7. Linux虚拟内存和物理地址的理解【转】

    本文转载自:http://blog.csdn.net/dlutbrucezhang/article/details/9058583 在多任务操作系统中的每一个进程都运行在一个属于它自己的内存沙盘中.这 ...

  8. Sql Server 创建表添加说明

    http://bbs.csdn.net/topics/340184487 在此感谢 提供参考 CREATE TABLE ToPayFee (    Id INT IDENTITY(1,1) PRIMA ...

  9. Leetcode——Target Sum

    Question You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you ha ...

  10. c# 、 Asp.net 获取本地IP和MAC地址

    using System; using System.Management; using System.Net; public class Program { static void Main(str ...