/**
* 动态代理类:先参考代理模式随笔,了解代理模式的概念,分为jdk动态代理和cglib,jdk动态代理是通过实现接口的方式创建代理类的,cglib是通过继承类的方式实现的代理类的
* jdk动态代理需要用到jdk自带的一个类Proxy来生成代理类,还需要一个提供执行方法的执行接口InvocationHandler.代理类通过底层反编译后可以看到是调用
* InvocationHandler的invoke方法实现
*
*
*/
//父接口
public interface IRun {
void run();
}
//被代理类
public class Runner implements IRun {
@Override
public void run() {
System.out.println("运动员开跑...............");
}
}
//实现一个执行类,代理类底层是通过这个类来执行被代理类的方法 public class MyInvocationHandler implements InvocationHandler {
private IRun run; //被代理类 public MyInvocationHandler(IRun run) {
this.run = run;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行之前进行检查");
method.invoke(run,args); //反射执行被代理类的方法
System.out.println("执行之后.....");
return null;
} //通过Proxy获取获取代理类
public IRun getProxy(){ return (IRun) Proxy.newProxyInstance(run.getClass().getClassLoader(),run.getClass().getInterfaces(),this);
} //Proxy.newProxyInstance()底层是调用ProxyGenerator.generateProxyClass来生成字节码的,这里模拟实现,将代理生成的字节码文件输出来,然后反编译
public static void createProxyClassFile(){//生成字节码对象
String name = "ProxyRun.class";
byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{IRun.class});
FileOutputStream out =null;
try {
out = new FileOutputStream( System.getProperty("user.dir") + File.separator + name);
out.write(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null!=out) try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
Runner runner = new Runner();//被代理类
MyInvocationHandler handler = new MyInvocationHandler(runner);//执行处理的类
IRun proxy = handler.getProxy();//获取代理类
proxy.run();//代理类执行方法
//输出代理类的字节码文件,通过反射可以看到实现原理
MyInvocationHandler.createProxyClassFile();
} }
//对代理类字节码文件反编译,可以看到是通过实现IRun接口
public final class $proxy0 class extends Proxy implements IRun {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0; public class(InvocationHandler var1) throws {
super(var1);
} public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final void run() throws {
try {
//可见底层是调用InvocationHandler的invoke方法
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final int hashCode() throws {
try {
return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m3 = Class.forName("builder.IRun").getMethod("run", new Class[0]); //run方法
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
//cglib实现动态代理,该方式因为不是jdk自带的,所以需要引入相应的依赖包(spring框架自带相应的依赖包了),代理类需要实现MethodInterceptor相当于jdk动态代理的InvocationHandler,
//覆写intercept相当于InvocationHandler的invoke方法,生成代理类是通过Enhancer类来生成的
public class Dog { public void sout(){
System.out.println("汪汪");
}
}
public class DogProxy implements MethodInterceptor { private Dog target;
public DogProxy(Dog target) {
this.target = target;
}
public Object bind(){
Enhancer enhancer = new Enhancer();//创建加强器,用来创建动态代理类
enhancer.setSuperclass(target.getClass());//为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
enhancer.setCallback(this); //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
return enhancer.create();
} @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始");
method.invokeSuper(o,objects);
System.out.println("结束");
return null;
}
}

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

  1. JDK动态代理和CGLib动态代理简单演示

    JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期间创建接口的代理实例. 一.首先我们进行JDK动态代理的演示. 现在我们有一个简单的业务接口Saying,如下: package te ...

  2. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  3. Spring -- <tx:annotation-driven>注解基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)的区别。

    借鉴:http://jinnianshilongnian.iteye.com/blog/1508018 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional ...

  4. Spring <tx:annotation-driven>注解 JDK动态代理和CGLIB动态代理 区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

  5. java的静态代理、jdk动态代理和cglib动态代理

    Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...

  6. jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)

    代理模式是一种很常见的模式,本文主要分析cglib动态代理的过程 1. 举例 使用cglib代理需要引入两个包,maven的话包引入如下 <!-- https://mvnrepository.c ...

  7. 代理模式之静态代理,JDK动态代理和cglib动态代理

    代理模式,顾名思义,就是通过代理去完成某些功能.比如,你需要购买火车票,不想跑那么远到火车站售票窗口买,可以去附近的火车票代售点买,或者到携程等第三方网站买.这个时候,我们就把火车站叫做目标对象或者委 ...

  8. Spring 静态代理+JDK动态代理和CGLIB动态代理

    代理分为两种:静态代理 动态代理 静态代理:本质上会在硬盘上创建一个真正的物理类 动态代理:本质上是在内存中构建出一个类. 如果多个类需要进行方法增强,静态代理则需要创建多个物理类,占用磁盘空间.而动 ...

  9. jdk动态代理和cglib动态代理的区别

    一.原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件 ...

  10. jdk 动态代理和 cglib 动态代理

    原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载 ...

随机推荐

  1. 如何用VMD将轨迹文件制作动画(转载)

    转载自:http://blog.sina.com.cn/s/blog_63f794950101dtte.html 很多同学想从dcd(NAMD)或者trr(gromac)文件提取一段轨迹文件做成动画. ...

  2. 区块链入门到实战(38)之Solidity – 条件语句

    Solidity支持条件语句,让程序可以根据条件执行不同的操作.条件语句包括: if if...else if...else if 语法 if (条件表达式) { 被执行语句(如果条件为真) } 示例 ...

  3. frozenset冻结集合函数

    1.描述 frozenset()返回一个冻结的集合,冻结后不能添加.删除和修改. set()无序且不重复,是可以变的,有add.remove.扩展:删除重复数据,还可以计算交集.差集.并集等 2.函数 ...

  4. Idea创建maven加载过慢解决方法

    添加标签:archetypeCataloginternal问题解决!

  5. C语言内存泄露很严重,如何应对?

    摘要:通过介绍内存泄漏问题原理及检视方法,希望后续能够从编码检视环节就杜绝内存泄漏导致的网上问题发生. 1. 前言 最近部门不同产品接连出现内存泄漏导致的网上问题,具体表现为单板在现网运行数月以后,因 ...

  6. Python中的协程,为什么说它的底层是生成器?

    我们曾经在golang关于goroutine的文章当中简单介绍过 协程 的概念,我们再来简单review一下.协程又称为是微线程,英文名是Coroutine.它和线程一样可以调度,但是不同的是线程的启 ...

  7. windows上部署rabbitmq遇到的一些问题及解决方法

    在目前这家公司,刚进公司的时候接手了一个服务,算是个比较完备的服务,其中几台电脑之间通信用到了rabbitmq,一开始没出什么问题,然后后来勒索病毒wanner cry来的时候,系服把所有服务器装了一 ...

  8. Ant Jmeter Jenkins生成html测试报告

    Ant配置1. 将jmeter安装目录或者源码目录下\apache-jmeter-3.1\extras的ant-jmeter-1.1.1.jar复制到ant安装目录下apache-ant-1.10.3 ...

  9. docker下部署jira破解版

    1. 制作Docker破解容器 在/opt/jira下新建一个Dockerfile文件 touch Dockerfile 编辑Dockerfile文件 vim Dockerfile FROM cpta ...

  10. liunx之firewalld&SELinux

    1.firewalld的基本使用 启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status f ...