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. 数据分析入门——IPython入门

    一.什么是IPython IPython的开发者吸收了标准解释器的基本概念,在此基础上进行了大量的改进,创造出一个令人惊奇的工具.在它的主页上是这么说的:“这是一个增强的交互式Python shell ...

  2. 零基础学Python-第二章 :Python基础语法-05.基础数据类型

    打开终端,输入python3,这就进入了python的命令提示符. 输入type(8),返回的是int类型.用来type来判断当前的是什么类型. 字符串8转int类型. 数字123转字符串 布尔类型的 ...

  3. windows10 环境下的RabbitMQ安装步骤(图文)

    第一步:下载并安装erlang 原因:RabbitMQ服务端代码是使用并发式语言Erlang编写的,安装Rabbit MQ的前提是安装Erlang. 下载地址:http://www.erlang.or ...

  4. pandas绘制矩阵散点图(scatter_matrix)的方法

    以 sklearn的iris样本为数据集 import matplotlib.pyplot as plt from scipy import sparse import numpy as np imp ...

  5. sqoop import mysql to hive table:GC overhead limit exceeded

    1. Scenario description when I use sqoop to import mysql table into hive, I got the following error: ...

  6. 如何发布自己的APP到Google Play上

    如何发布自己的APP到Google Play上 参考链接: https://justforuse.github.io/blog/zh-cn/2019/08/publish-your-own-app-t ...

  7. [转]gcc的__builtin_函数介绍

    链接地址:https://blog.csdn.net/jasonchen_gbd/article/details/44948523

  8. 对于新手用c#中的delegate(委托)和event(事件)

    一.delegate到底是什么东西 delegate允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m,说白了就是可以把方法当作参数传递.delegate既可以引用静态函数 ...

  9. log4net使用简明教程,快看看哟

    在项目当中经常会遇到各种各样的问题,如何可以尽快找到问题,那么就只能靠日志了,所以一个系统的日志是否完备合理就尤为重要. 在日志管理插件中log4net相当流行,下面就简单说明一下使用方法. log4 ...

  10. jquery img src赋值

    不用Jquery时:document.getElementById("imageId").src = "xxxx.jpg"; 用Jquery时:$(" ...