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. VPB编译日志2

    1>------ 已启动全部重新生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake do ...

  2. webpack 4 教程

    webpack 4 教程:https://blog.zfanw.com/webpack-tutorial/

  3. 海思HI2115芯片-NB-IOT模块向外发短信测试

    1. 说是有短信这个功能,测试下怎么使用?先使能BIP功能 AT+NCONFIG=ENABLE_BIP,TRUE 给SIM卡上电 AT+NUICC= 查询下短信中心服务号码 AT+CSCA? 发送短信 ...

  4. Windows Server 2012 安装 .NET 3.5 解决办法

    我遇到的每台Windows Server 2012都会遇到无法通过控制面板进行.net3.5安装的问题,在网上找了很多办法都不适合自己,最后研究出来一个办法就是 1.首先从镜像提取sxs文件放置到一个 ...

  5. 实验1 C 语言开发环境使用和数据类型、运算符、表达式

    # include <stdio.h> int main() { int x; printf("x:\n"); scanf("%d",&x) ...

  6. 记联想SR850 Raid配置的一个bug

    管理raid阵列时,如果要删除某个指定的阵列,则需要选中阵列名而不能选中虚拟磁盘.如果选中的是虚拟磁盘,点击删除后,会删除整个阵列列表里的第一个阵列,而非虚拟磁盘所在的阵列. 过程如下 联想SR850 ...

  7. SPSS数据分析基础考题

    选择题 1. SPSS发行版本的说法,正确的是: B A. 两年发行一个新版本 B.一年发行一个新版本 C.没有任何规律 D.三年发行三个新版本 2.哪些是SPSS统计分析软件的基本窗口: A A.结 ...

  8. python线程池ThreadPoolExecutor(上)(38)

    在前面的文章中我们已经介绍了很多关于python线程相关的知识点,比如 线程互斥锁Lock / 线程事件Event / 线程条件变量Condition 等等,而今天给大家讲解的是 线程池ThreadP ...

  9. 搭建Springboot

    这几天一直在研究IDEA上面怎么搭建一个web-mvc的SpringBoot项目,看网上的教程一步步的搭建,可是还是出现一堆的问题. 为了让大家以后少走一些弯路,我在这里分享一下我这几天研究的成果,也 ...

  10. 《ucore lab6》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 使用 Round Robin 调度算法(不需要编码) 题目 完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件) 个人完成 ...