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 {
@Override
public int add(int i, int j) {
int result = i + j;
System.out.println("add:"+result);
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
System.out.println("sub:"+result);
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
System.out.println("mul:"+result);
return result;
}
@Override
public 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,InvocationTargetException
System.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();
}
@Override
public 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方式要更为合适一些。
JAVA学习之动态代理的更多相关文章
- Java学习之动态代理篇
Java学习之动态代理篇 0x00 前言 在后面的漏洞研究的学习中,必须要会的几个知识点.反射机制和动态代理机制.至于反射的前面已经讲到过了,这里就不做更多的赘述了. 0x01 动态代理 这里先来讲一 ...
- Java学习笔记--动态代理
动态代理 1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy ...
- Java学习笔记——动态代理
所谓动态,也就是说这个东西是可变的,或者说不是一生下来就有的.提到动态就不得不说静态,静态代理,个人觉得是指一个代理在程序中是事先写好的,不能变的,就像上一篇"Java学习笔记——RMI&q ...
- java学习之动态代理模式
package com.gh.dynaproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Metho ...
- java 笔记(3) —— 动态代理,静态代理,cglib代理
0.代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口. 代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常会存 ...
- java中的动态代理机制
java中的动态代理机制 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现 ...
- 深度剖析java中JDK动态代理机制
https://www.jb51.net/article/110342.htm 本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定 ...
- 一文读懂Java中的动态代理
从代理模式说起 回顾前文: 设计模式系列之代理模式(Proxy Pattern) 要读懂动态代理,应从代理模式说起.而实现代理模式,常见有下面两种实现: (1) 代理类关联目标对象,实现目标对象实现的 ...
- java反射和动态代理实现与原理详细分析
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 代理模式是常用的java设计模式, ...
随机推荐
- Delphi TRect函数例子
{ 在网上看到个这个例子感觉还不错,将它移到自己的博客里没事的时候看看: TRect 作用:保存一个矩形的左上角和右下角的坐标值: 声明: type TRect = ...
- HDU1548:A strange lift(Dijkstra或BFS)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1548 题意:电梯每层有一个数,例如第n层有个数k, 那么这一层只能上k层或下k层,但是不能低于一层或高 ...
- hcharts中文网 一个js图表库
http://www.bossidc.com/info/gongju/2013/0717/2133.html hcharts源码包下载 http://www.hcharts.cn/demo/hig ...
- C# 堆栈和堆 Heap & Stack
首先堆栈和堆(托管堆)都在进程的虚拟内存中.(在32位处理器上每个进程的虚拟内存为4GB) 堆栈stack 堆栈中存储值类型. 堆栈实际上是向下填充,即由高内存地址指向低内存地址填充. 堆栈的工作方式 ...
- MySQL密码丢失,解决方法
我的MySQ安装路径是:D:\Program Files\MySQL 1.所以先cmd下切入盘 输入-> D: 输入->cd "D:\Program Files\MySQL\My ...
- C#综合揭秘——细说进程、应用程序域与上下文之间的关系
引言 本文主要是介绍进程(Process).应用程序域(AppDomain)..NET上下文(Context)的概念与操作.虽然在一般的开发当中这三者并不常用,但熟悉三者的关系,深入了解其作用,对提高 ...
- Spring @Aspect进行类的接口扩展
Spring @Aspect进行类的接口扩展: XML: <?xml version="1.0" encoding="UTF-8"?> <be ...
- 性能优化实战案例——助力某移动OA系统
前言 最近连续接触了4个OA系统,均存在着不同的性能问题,本文记述对某移动OA系统的优化全过程,让看官们对数据库优化流程有一个了解,并揭开隐式转换这无情杀手的神秘面纱. 本文使用的工具:SQL专家云平 ...
- FP Tree算法原理总结
在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题,FP Tree算法(也称F ...
- (四)Hololens Unity 开发之 凝视系统
学习源于官方文档 Gaze in Unity 笔记一部分是直接翻译官方文档,部分各人理解不一致的和一些比较浅显的保留英文原文 HoloLens 有三大输入系统,凝视点.手势和声音 ~ 本文主要记录凝视 ...