JAVA学习之动态代理

JDK1.6中的动态代理

在Java中Java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成一个动态代理对象。JDK提供的代理只能针对接口做代理

java.lang.reflect.Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
public static InvocationHandler getInvocationHandler(Object proxy) // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
public static Class<?> getProxyClass(ClassLoader loader, 
Class<?>... interfaces)// 方法 3:该方法用于判断指定类对象是否是一个动态代理类
public static boolean isProxyClass(Class<?> cl) // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

java.lang.reflect.InvocationHandler:调用处理器接口,自定义invokle方法,用于实现对于真正委托类的代理访问。

/**该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象(反射中Method对象)第三个参数是调用方法的参数列表。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

 使用Proxy类中的newProxyInstance方法创建代理对象

参数:loader - 定义代理类的类加载器interfaces - 代理类要实现的接口列表h - 指派方法调用的调用处理程序 返回: 一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException

实例

接口:

package com.jalja.org.base.poxy;
public interface ArithmeticCalculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);
}

实现类:

package com.jalja.org.base.poxy;
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {@Overridepublic int add(int i, int j) {int result = i + j;System.out.println("add:"+result);return result;}@Overridepublic int sub(int i, int j) {int result = i - j;System.out.println("sub:"+result);return result;}@Overridepublic int mul(int i, int j) {int result = i * j;System.out.println("mul:"+result);return result;}@Overridepublic int div(int i, int j) {int result = i / j;System.out.println("div:"+result);return result;}
}

代理类及使用:

package com.jalja.org.base.poxy.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.jalja.org.base.poxy.ArithmeticCalculator;
import com.jalja.org.base.poxy.ArithmeticCalculatorImpl;
public class MyInvocationHandler implements InvocationHandler{private Object target;//目标对象(对哪个对象做动态代理)public MyInvocationHandler(Object target) {this.target=target;}@Override/*** proxy - 在其上调用方法的代理实例* method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。* args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。 * return - 返回代理对象*/public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//obj - 从中调用底层方法的对象//args - 用于方法调用的参数 //public Object invoke(Object obj, Object... args)throws IllegalAccessException, IllegalArgumentException,InvocationTargetExceptionSystem.out.println(method.getName()+"方法前置。。。。。。。。。。。。。。。。");Object result=method.invoke(target, args);System.out.println("method:"+method);System.out.println(method.getName()+"方法后置。。。。。。。。。。。。。。。。");return result;}public static void main(String[] args) {/*参数:loader - 定义代理类的类加载器interfaces - 代理类要实现的接口列表h - 指派方法调用的调用处理程序 返回: 一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException*/ArithmeticCalculator ac=new ArithmeticCalculatorImpl();//Object proxy=Proxy.newProxyInstance(ac.getClass().getClassLoader(), ac.getClass().getInterfaces(), new MyInvocationHandler(ac));ArithmeticCalculator proxy=(ArithmeticCalculator)Proxy.newProxyInstance(ac.getClass().getClassLoader(), ac.getClass().getInterfaces(), new MyInvocationHandler(ac));proxy.add(10, 100);proxy.sub(20, 10);}}

Cglib动态代理 
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

 Demo:

package com.jalja.org.base.poxy.Cglib;import java.lang.reflect.Method;import com.jalja.org.base.poxy.ArithmeticCalculatorImpl;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor{private Object target;  /** * 创建代理对象 * @param target * @return */  public Object getInstance(Object target) {  this.target = target;  Enhancer enhancer = new Enhancer();  enhancer.setSuperclass(this.target.getClass());  // 回调方法  enhancer.setCallback(this);  // 创建代理对象  return enhancer.create();  }  @Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("前置代理");  //通过代理类调用父类中的方法  Object result = proxy.invokeSuper(obj, args);  System.out.println("后置代理");  return result;  }public static void main(String[] args) {CglibProxy cglib=new CglibProxy();  ArithmeticCalculatorImpl bookCglib=(ArithmeticCalculatorImpl)cglib.getInstance(new ArithmeticCalculatorImpl());  bookCglib.add(10, 30);}
}

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。

转载于:https://www.cnblogs.com/jalja/p/6514829.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401438.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

net开源项目

1 以色列 特思开源软件 http://cn.tersus.com/#Id3924 2 开源社区 http://www.ctochina.net/ .NET开源项目链接 http://www.cnblogs.com/dustinyang/articles/361479.html项目网址简介Rainbowhttp://www.rainbowportal.net/ http://sourceforge.net/projects/rainbowportal/The…

screen状态变Attached连接会话失败

使用xshell远程登录主机&#xff0c;使用screen命令启动程序运行至后台&#xff0c;意外发现screen session的状态为Attached&#xff0c;使用命令screen -r &#xff1c;session-id>,提示失败信息&#xff0c;重复多次无果。 解决方法&#xff1a;把自己踢掉&#xff0c;然…

引用类型赋值

转载于:https://www.cnblogs.com/dongyuhan/p/6519711.html

poj2624 4th Point

纯水题&#xff0c;注意交点不一定是第二个点和第三个点 #include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<algorithm>using namespace std;struct Vector{ double x; double y;};struct point{ double…

Windows Phone开发(30):图形 转:http://blog.csdn.net/tcjiaan/article/details/7453028

图形如矩形、椭圆、路径等都从Shape类派生&#xff0c;它们一般表示规则或不规则图形&#xff0c;这些图形都是简单的二维图形&#xff0c;我相信大家都能理解的。 例一&#xff1a;矩形。 请看下面的XAML代码。 [html] view plaincopyprint? <Rectangle RadiusX"20&q…

安装android sdk,后出现导出错误,提示命令行找不到解决方案

安装android sdk&#xff0c;后出现导出错误&#xff0c;提示命令行找不到解决方案 The steps. Rename android sdk tool folder : [Your Android SDK root]/tools -> toolsXXXX Download SDK Tools: http://dl-ssl.google.com/android/repository/tools_r25.2.5-windows.z…

Windows Phone开发(46):与Socket有个约会 转:http://blog.csdn.net/tcjiaan/article/details/7669315...

不知道大家有没有“谈Socket色变”的经历&#xff1f;就像我一位朋友所说的&#xff0c;Socket这家伙啊&#xff0c;不得已而用之。哈&#xff0c;Socket真的那么恐怖吗&#xff1f; 其实这话一点也不假&#xff0c;Socket有时候真的不太好操控&#xff0c;也不好维护&#xff…

百度分享插件wbuid属性无法@指定微博

好久不写博客&#xff0c;看到很多人遇到相关的问题&#xff0c;决定写一篇拯救大家于水火 现象很简单&#xff0c;你要是根据官网的例子来&#xff0c;肯定出错。。。。 官网上教你如果想在分享时自动""并且在分享后提示关注要用wbuid这个属性来配置微博id对不对&am…

lucene计分公式详解

lucene计分工具Similarity&#xff1a; 查询query q 相对于文档document d的得分跟空间向量里面 查询q 与 文档d 的余弦值有关。文档d 矢量 与 查询q 矢量越靠近&#xff0c;文档等分越高。转载于:https://www.cnblogs.com/deacon/articles/2608078.html

10 进制转 2 进制、16 进制

为什么80%的码农都做不了架构师&#xff1f;>>> function IntToBin(Value: LongInt; Size: Integer): String; vari: Integer; beginResult:;for i:Size-1 downto 0 dobeginif Value and (1 shl i)<>0 thenResult:Result1elseResult:Result0;end; end;//举例…

SSH之Hibernate总结篇

Hibernate hibernate 简介&#xff1a; hibernate是一个开源ORM(Object/Relationship Mipping)框架&#xff0c;它是对象关联关系映射的持久层框架&#xff0c;它对JDBC做了轻量级的封装&#xff0c;而我们java程序员可以使用面向对象的思想来操纵数据库。 为什么要用hibernate…

ubuntu基本命令

用户chmod chmod 777 /目录/ -R参数&#xff0d;R是对该目录及子目录的所有文件授权。转载于:https://www.cnblogs.com/cenmny/p/6534410.html

Vue开发规范

规范目的 为提高团队协作效率 便于后台人员添加功能及前端后期优化维护 输出高质量的文档 命名规范 为了让大家书写可维护的代码&#xff0c;而不是一次性的代码 让团队当中其他人看你的代码能一目了然 甚至一段时间时候后你再看你某个时候写的代码也能看 css命名规范 遵循…

.toString(c) 将数字值 渲染成 货币形式

<system.web><!--设置 语言 产生货币样式--><!--<globalization culture"en-GB" uiCulture"en-GB"/>--> ///£95.00 <!--<globalization culture"en-US" uiCulture"en-US"/>--> //…

Vue项目搭建流程

Vue 简介 vue是目前前端最具前景的框架之一&#xff0c;能帮助我们快速搭建并开发前端项目。 Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;…

x=a%pq与x=a%p,x=a%q的关系(pq互质)

http://prayer.hustoj.com/problem.php?id1770 我们 口胡 证明一下&#xff1b; a%pa%qx; tpxat’qx; ∴tpt’q; ∵(p,q)1; 所以 tpt’q; 即 kqpk’pqtpt’q; kqpxa; a%(qp)x; #include<iostream> #include<cstdio> #include<cstring> #define L…

Vue模板语法详解

vue基础、安装、介绍双大括号&#xff08;Mustache语法&#xff0c;又叫胡子语法&#xff09;v-textv-htmlv-showv-if、v-else-if、v-elsev-show 与 v-if 的区别v-forv-for 中的 keyv-if 与 v-for 一起使用v-on&#xff08;缩写&#xff1a; &#xff09;v-bind&#xff08;缩写…

C# 中利用 Conditional 定义条件方法

利用 Conditional 属性&#xff0c;程序员可以定义条件方法。Conditional 属性通过测试条件编译符号来确定适用的条件。当运行到一个条件方法调用时&#xff0c;是否执行该调用&#xff0c;要根据出现该调用时是否已定义了此符号来确定。如果定义了此符号&#xff0c;则执行该调…

小白如何从零开始运营微信公众号?

小白如何从零开始运营微信公众号&#xff1f; 一、公众号定位&#xff0c;名称&#xff0c;头像 第一步公众号定位&#xff0c;最重要。如果你自己都讲不清楚自己是干嘛的&#xff0c;还有谁愿意来关注你呢&#xff1f;无论是旅游攻略还是美妆种草&#xff0c;成长干货还是养生…

软件测试技术lab1 2017.3.13

1.安装Junit和Hamcrest 2. 安装Eclemma 3.三角问题的测试用例 4.测试结果及coverage覆盖 转载于:https://www.cnblogs.com/kale12/p/6543904.html