1. jdk静态代理

  jdk静态代理主要使用硬编码实现.他通过对在代理类中持有委托类的引用,来打到在委托类方法执行前和执行后进行处理,实现简单,容易理解.

  代码如下:

  1.业务逻辑接口

 package jdkStaticProxy;

 public interface Service {

     public void doService();

 }

  2.业务逻辑实现类

 package jdkStaticProxy;

 public class ServiceImpl implements Service {

     @Override
public void doService() {
System.out.println("this is doService method");
}
}

  3.代理类

 package jdkStaticProxy;

 public class ServiceProxy implements Service {

     private Service service;

     public ServiceProxy(Service service) {
this.service = service;
} @Override
public void doService() {
System.out.println("there is before method");//前置处理方法
service.doService();//业务逻辑方法
System.out.println("there is after method");//后置处理方法
}
}

  在代理类中持有一个委托类的应用,以达到在代理类中进行相关处理.

  4.测试类

 package jdkStaticProxy;

 public class Main {

     public static void main(String[] args) {
Service service=new ServiceImpl();
Service serviceProxy=new ServiceProxy(service);
serviceProxy.doService();
} }

  以上就是jdk静态代理,很容易理解,但是他的问题也显而易见----dk静态代理因为是硬编码实现,所以可能会存在大量的重复代码.加入我们的service有10个方法,那么我们的代理类中就必须有10个对应的代理方法,这样的工作量是非常大.

2. jdk动态代理

  jdk动态代理主要使用反射实现.要使用jdk代理必须实现一个接口,原因是jdk代理是用代理类替换委托类进行方法调用,为了让代理能够完成替换,就必须实现一个接口,这样jdk就能生成对应的代理类.代理类的生成主要通过一个Proxy工厂生成,代理类的方法通过调用一个InvocationHandler接口的invoke方法执行.

  代码如下:

  1.业务逻辑接口

    同静态代理

  2.业务逻辑实现类

    同静态代理

  3.InvocationHandler

 package jdkDynamicProxy;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("there is before method"); method.invoke(target,args); System.out.println("there is after method"); return null;
} }

    从代码里面可以看出来,代理类持有委托类的引用.委托类的方法是通过反射来进行调用的.method是委托类的方法.

  4.测试类

package jdkDynamicProxy;

import java.lang.reflect.Proxy;

public class Main {

    public static void main(String[] args) {
ServiceImpl service=new ServiceImpl();
MyInvocationHandler myInvocationHandler=new MyInvocationHandler(service); Service service1= (Service) Proxy.newProxyInstance(
service.getClass().getClassLoader(),//委托类的类加载器
service.getClass().getInterfaces(),//委托类的接口
myInvocationHandler);//InvocationHandler service1.doService(); System.out.println("实际类型:"+service1.getClass());
} }

  Proxy是一个工厂类,调用newProxyInstance生成一个代理类,传入委托类加载器和委托类的接口是为了创建一个能够替换委托类的代理类(为什么需要这两个参数请了解JVM如何判断两个类相等),InvocationHandler为代理类的逻辑方法.代码中的service1实际类型是com.sun.proxy.$Proxy0.代理类的创建是通过反射创建,有兴趣的读者可以研究Proxy的源码,也可以看这里

3. cglib动态代理

  cglib是一个开源库,他不需要委托类实现一个接口,他是通过创建一个继承委托类的代理类,来进行强化方法,代理类的实现方法通过调用MethodInterceptor的intercept方法.创建代理类主要借助asm这个java字节码生成框架.

  代码如下:

  1.业务逻辑类

    同静态代理

  2.intercept

 package cglibProxy;

 import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class MyInterceptor implements MethodInterceptor { @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("-----before");
methodProxy.invokeSuper(o,objects);//调用父类(业务逻辑)方法
System.out.println("-----after");
return null;
} }

  其中method是委托类的方法,methodProxy是代理类的代理方法.

  3.测试方法

 package cglibProxy;

 import net.sf.cglib.proxy.Enhancer;

 public class Main {

     public static void main(String[] args) {

         Enhancer enhancer=new Enhancer();//该类是cglib的字节码生成器,能够直接生成对应代理类的字节码
enhancer.setSuperclass(Service.class);//继承委托类(final类不可被继承)
enhancer.setCallback(new MyInterceptor());//设置回调
Service service= (Service) enhancer.create();//生成代理对象 service.doService();
System.out.println("实际类型:"+service.getClass()); }
}

    代理类对象是由Enhancer类创建的。Enhancer是CGLIB的字节码增强器,可以很方便的对类进行拓展.通过设置回调方法和委托类,生成对应代理类的字节码,然后将代理类加载进来,生成代理对象.

    创建代理类的步骤如下:

      1.生成代理类的二进制字节码文件

      2.加载二进制字节码,生成Class对象( 例如使用Class.forName()方法 )

      3.通过反射机制获得实例构造,并创建代理类对象

    cglib原理请看这里

4. 各代理对比

  1.jdk静态代理:实现简单易懂,但是由于是硬编码实现,所以可能会出现大量重复代码.

  2.jdk动态代理:通过反射机制创建代理类以及代理类方法调用,他在创建代理类的效率上会比cglib高,但是在调用方法的效率上比cglib低.

  3.cglib动态代理:通过生成字节码的方式创建代理类,他在创建代理类的效率上由于要生成字节码以及加载类所以比jdk代理低,但是方法执行效率上由于是直接执行,不需要进行反射所以效率比jdk代理高.

jdk代理与cglib代理的更多相关文章

  1. 总结两种动态代理jdk代理和cglib代理

    动态代理 上篇文章讲了什么是代理模式,为什么用代理模式,从静态代理过渡到动态代理. 这里再简单总结一下 什么是代理模式,给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原 ...

  2. spring的AOP动态代理--JDK代理和CGLIB代理区分以及注意事项

    大家都知道AOP使用了代理模式,本文主要介绍两个代理模式怎么设置以及区别,对原文一些内容进行了引用后加入了自己的理解和更深入的阐述:   一.JDK代理和CGLIB代理的底层实现区别* JDK代理只能 ...

  3. 关于JDK动态代理与Cglib代理

    关于JDK动态代理与Cglib代理 最近有时间学习一下SpringAOP源码,底层用到了代理,大概是这样的: 当需要被代理的类实现了接口,则使用JDK动态代理创建代理对象,增加增强操作执行目标方法 当 ...

  4. Java中jdk代理和cglib代理

    代理模式 给某一个对象提供一个代理,并由代理对象控制对原对象的引用.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 在Java中代理模式从实 ...

  5. java代理,静态代理、jdk代理、cglib代理、Aspectj

    我实在接触spring的时候才接触到代理这个东西的,一直想整理一下笔记. 什么是代理模式:代理模式是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能.简单来说就是要创建一个新的对象,我 ...

  6. java代理(静态代理和jdk动态代理以及cglib代理)

    版权声明:本文为Fighter168原创文章,未经允许不得转载.   目录(?)[+]   说到代理,脑袋中浮现一大堆代理相关的名词,代理模式,静态代理,jdk代理,cglib代理等等. 记忆特别深刻 ...

  7. (转)Java动态代理与CGLib代理

    <br>public class UserDAOImpl{ <br><br>    public void save() { <br>        / ...

  8. IT忍者神龟之Java动态代理与CGLib代理

    <br>public class UserDAOImpl{ <br><br>    public void save() { <br>        / ...

  9. jdk代理和cglib代理

    1.jdk静态代理(静态代理和动态代理) 本质:在内存中构建出接口的实现类. 缺陷:只能对实现接口的类实现动态代理, 使用cglib可以对没有实现接口的类进行动态代理. 2.cglib动态代理     ...

  10. jdk动态代理与cglib代理、spring aop代理实现原理

    原创声明:本博客来源与本人另一博客[http://blog.csdn.net/liaohaojian/article/details/63683317]原创作品,绝非他处摘取 代理(proxy)的定义 ...

随机推荐

  1. java连接数据库失败:java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

    说一下我的情况: 在测试环境中运行没有任何问题,但是导出war包之后,就将war包上传到线上服务器的webapps目录下,然后启动Tomcat,等待Tomcat将上传的war包解压(此时Tomcat没 ...

  2. Spring cloud微服务安全实战-3-8API安全机制之Https

    Https访问 1.验证双方的身份. 2.一旦建立连接,对数据进行封装加密 这里先生成一个自己自签的证书,不是第三方颁发的,第三方颁发的要花钱. 第二是做一些配置,让程序支持https 安装了java ...

  3. 【设备问题】罗技M590鼠标无法连接Macbook Pro问题解决

    问题现象 罗技蓝牙鼠标连接的时候一直显示连接中,但是一直连接不上. 解决方法 长按那个切换模式的按钮,重置下,再点击连接,显示能够连接成功.

  4. RabbitMQ 入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)

    发布/订阅 在上篇第二部分教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式 ...

  5. Spring Boot与Redis的集成

    Redis是一个完全开源免费的.遵守BSD协议的.内存中的数据结构存储,它既可以作为数据库,也可以作为缓存和消息代理.因其性能优异等优势,目前已被很多企业所使用,但通常在企业中我们会将其作为缓存来使用 ...

  6. jenkins--master/slave模式---master是容器版---slave是非容器版

    实验架构: 192.168.0.96 gitlab 192.168.0.97 jenkins.tomcat 192.168.0.98 harbor.docker集群.git.jdk.maven 1.先 ...

  7. yarn那些事儿

    本篇文章立足于mac. 一.安装yarn 1.通过homebrew brew update brew install yarn 2.通过脚本 curl -o- -L https://yarnpkg.c ...

  8. IOPS 测试工具 FIO

    FIO是测试IOPS的非常好的工具,用来对硬件进行压力测试和验证,支持13种不同的I/O引擎. fio-2.8下载: wget http://brick.kernel.dk/snaps/fio-2.8 ...

  9. mongodb4.0 安装

    下载: wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.9.tgz 解压缩 tar -zxvf mongodb-linux ...

  10. 【Axure8】利用中继器(Repeater)实现表格数据的增删改

    利用Repeater实现对Table数据的增删改操作. 先拖入必需的控件:rectangle.text field.droplist.button.table.repeater.具体信息如图. 为方便 ...