- 浏览: 183328 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
delu577025500:
f — 表示返回数据列,如“snd1l1yr”。更详细的参见附 ...
连接雅虎财经API获取股票信息 -
kizz:
您好,请问如何计算压缩的时间。
利用ant.jar进行解压缩 -
yangxiutian:
想查查新版的struts2的工作原理 网上全是旧版的
struts2 StrutsPrepareAndExecuteFilter 源码分析 -
695165987:
KM文件夹 怎么下载上面的文件夹啊,一个个的下载很累啊~大哥知 ...
sap portal KM 文件夹布局配置 -
nurenok:
postInit(dispatcher, filterCo ...
struts2 StrutsPrepareAndExecuteFilter 源码分析
一篇杂文,写到哪就说到哪。在一些框架中有所谓的截面(aop),这些应用主要就是使用了JAVA的动态代理机制。截面或者说是拦截器所做的事情就是把一些共同的功能代码进行了抽取,简化开发以及维护。比如说,某些业务需要记录日志,需要进行功能验证。
先把用到的代码做一些简单的说明:
Ø ImasterBusiness:主业务接口
Ø MasterBusiness:主业务接口的一个实现类
Ø MasterBusinessIntercepter:你叫拦截器也好,叫截面也好的一个类
Ø MasterBusinessHander:处理器
Ø MasterBusinessProxy:静态代理类
1. 静态代理
代理模式主要就是为了隐藏真实的业务主体,来达到一种封装的效果。静态代理模式是最简单的一种,说白了就是为每一个真实的业务主体都手动创建一个代理类。先看下面的代码
l 业务接口:
public interface IMasterBusiness {
public void moreMoney();
}
l 真实业务主体
public class MasterBusiness implements IMasterBusiness {
/* (non-Javadoc)
* @see test.IMasterBusiness#moreMoney()
*/
@Override
public void moreMoney() {
System.out.println("股票飘红!");
}
}
l 代理类
public class MasterBusinessProxy implements IMasterBusiness{
private IMasterBusiness imb;
public MasterBusinessProxy(IMasterBusiness imb){
this.imb = imb;
}
@Override
public void moreMoney() {
buy();
imb.moreMoney();
sale();
}
//buy,sale就是一些共同的功能代码,例如记录日志,功能验证等
private void buy(){
System.out.println("抄底");
}
private void sale(){
System.out.println("高抛");
}
}
l 使用代理:
public static void main(String[] args) {
IMasterBusiness imb = new MasterBusiness();
IMasterBusiness imbp = new MasterBusinessProxy(imb);
imbp.moreMoney();
}
l 运行结果:
抄底
股票飘红!
高抛
静态代理有一个问题就是需要我们手动创建代理类,如果业务方法不止一个,那么就要在每个业务方法中都加入buy()以及sale()方法。如果业务类不止一个,我们就要分别创建代理类。代码量增大,也为之后的维护增加了难度。解决的办法就是动态代理模式
动态代理模式
动态代理需要引用java中的Proxy类以及InvocationHandler接口。先把实现代码贴上
l 处理器
public class MasterBusinessHander implements InvocationHandler {
//被代理的对象
private Object masterBusinee;
//拦截器
private MasterBusinessIntercepter intercepter = new MasterBusinessIntercepter();
public MasterBusinessHander(Object masterBusinee){
this.masterBusinee = masterBusinee;
}
/* (non-Javadoc)
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
* proxy:代理类
* method:要调用的业务方法
* args:也无方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
if(method.getName().equals("moreMoney")){
intercepter.buy();
result = method.invoke(masterBusinee, args);
intercepter.sale();
}else{
result = method.invoke(masterBusinee, args);
}
return result;
}
}
l 调用:
public static void main(String[] args) throws Exception {
//创建一个调用器
MasterBusinessHander hander = new MasterBusinessHander(new MasterBusiness());
//拆分生成代理的步骤,方便后面的介绍
Class<?> mbClass = Proxy.getProxyClass(MasterBusiness.class.getClassLoader(), MasterBusiness.class.getInterfaces());
Constructor<?> constructor = mbClass.getConstructor(new Class[]{InvocationHandler.class});
Object obj = constructor.newInstance(hander);
if(obj instanceof IMasterBusiness){
IMasterBusiness mb = (IMasterBusiness)obj;
mb.moreMoney();
}else{
System.out.println("代理失败");
}
}
Proxy:
Java 动态代理机制的主类,提供了2个静态方法来生成指定接口的代理类或者对象
//获取指定接口的动态代理类的类对象
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
//生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
InvocationHandler:
调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象,第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
Object invoke(Object proxy, Method method, Object[] args)
拆分动态代理对象创建过程
1. 首先是new 一个InvocationHandler的实现类对象 new MasterBusinessHander(new MasterBusiness()) 需要为调用处理器指定一个真实的业务对象,我们调用代理类的方法最终还是要调用到真实业务对象的方法,就是我们在这里提供的业务对象。 2. 根据指定的接口生成一个代理类对象 Proxy.getProxyClass(MasterBusiness.class.getClassLoader(), MasterBusiness.class.getInterfaces()); 在getProxyClass这个方法里会对接口数组进行一些验证,而且会把创建的代理对象类缓存到一个map(暂称为proxymap)中,类加载器作为proxymap的key,proxymap的value又是一个map(暂称为valuemap),valuemap的key是接口数组生产的一个对象,value就是我们创建的代理类对象。这些可以看看Proxy的代码。 3. 获取代理类的构造器 mbClass.getConstructor(new Class[]{InvocationHandler.class}) 我之前一直没有弄明白这个mbClass到底是一个什么样的类,看到下面这张图就可以看得很明白了。$ProxyN就是我们生产的代理类($以及N是Proxy定义的一个明白规则),这个类实现业务接口A,B,X,同时继承了Proxy类。在Proxy类中定义了一个protect访问权限的构造器 protected Proxy(InvocationHandler h) { this.h = h; }
4. 通过构造函数对象创建动态代理类实例 constructor.newInstance(hander); 在创建代理对象的过程中用到了很多反射方面的知识。 |
待解决的问题
查看Proxy的源码,生成代理类的代码如下:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces);
try {
// 动态地定义新生成的代理类
proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
sun.misc.ProxyGenerator没有公开代码,proxy到底如何调用处理器InvocationHandler我们就无法得知了,一个牛人给出了一个推演
// 假设代理类为 SimulatorProxy, 其类声明将如下 final public class SimulatorProxy implements businessInterface { // 调用处理器对象的引用 protected InvocationHandler handler; // 以调用处理器为参数的构造函数 public SimulatorProxy(InvocationHandler handler){ this.handler = handler; } // 实现接口方法 public void businessMethod(int arg1, long arg2, String arg3) throws ExceptionA, ExceptionB { // 第一步是获取方法的 Method 对象 java.lang.reflect.Method method = null; try{ method = businessInterface.class.getMethod( " businessMethod ", new Class[] {int.class, long.class, String.class} ); } catch(Exception e) { } // 第二步是调用 handler 的 invoke 方法分派转发方法调用 Object r = null; try { // 对于原始类型参数需要进行装箱操作,高级别版本的JDK可以自动装箱 r = handler.invoke(this, method, new Object[] { arg1, arg2, arg3}); }catch(Throwable e) { } } } |
这个推演的思路个人认为是正确的,也解释了我的疑惑
发表评论
-
DWR 2
2011-06-21 13:05 1082后续: 1. 拦截器 uk.ltd.get ... -
DWR 1
2011-06-21 12:58 921原文:http://www.blogjava.net/Supe ... -
log4j.properties的路径问题
2011-06-20 11:59 5440log4j.properties如果放在web-inif/cl ... -
Class.forName
2011-06-19 19:55 1197Class.forName(xxx.xx.xx) 返回 ... -
myeclipse优化 Maven
2011-06-18 09:11 82111.禁用myeclipse updating indexes ... -
ThreadLocal学习2
2011-06-10 13:15 1165典型实例 Hiberante的HibernateSessio ... -
【转】ThreadLocal学习一
2011-06-10 11:05 1356我们知道Spring通过各种D ... -
httpUrlConnection参数详解
2011-06-02 12:54 13496// 设置是否向httpUrlConnection输出,因为这 ... -
HttpURLConnection使用代理服务器
2011-06-02 11:48 2531目前网络上最流行的协 ... -
连接雅虎财经API获取股票信息
2011-06-02 11:29 24684一直想自己做个简单的股票系统,来记录股票的价格。在网上看了下, ... -
java字符串split方法的诡异
2011-06-01 18:01 975String str = "#123" ... -
eclipse插件
2011-05-30 14:05 812正则表达式插件 http://regex-util.sourc ... -
Hibernate annotation学习笔记1
2011-05-19 17:16 1一系列笔记所使用的数据库表关系图 -
利用ant.jar进行解压缩
2011-05-19 16:22 4131package com.zoucq; import java ... -
JSPWiki的安装
2011-05-19 15:02 2381平时喜欢用word,excel文档保存一些知识点,日子久了就发 ... -
quartz监听器
2011-05-18 15:32 6903Quartz主要包含三个组件job,trigger,sched ... -
junit4新框架hamcrest的assertThat
2011-05-18 13:13 7409assertThat JUnit4.4引入了Hamcrest ... -
junit3与junit4的区别
2011-05-18 13:00 8742Junit4最大的亮点就是引入了注解(annotation), ... -
quartz日记4-触发器
2011-05-17 17:16 1103SimpleTrigger 如果需要计 ... -
quartz日记3-quartz的基本类
2011-05-17 16:46 688Quartz的几个核心的接口和类为: Job接口:自 ...
相关推荐
总结来说,Java动态代理通过`Proxy`和`InvocationHandler`提供了灵活的代码扩展机制,可以在运行时为对象创建代理,实现在不修改原有代码的基础上添加额外功能。这在处理需要拦截和增强的对象时非常有用,例如日志...
### Java 动态代理Proxy应用和底层源码分析 #### 一、Java动态代理简介 Java动态代理是一种在运行时动态生成代理类的技术,通过该技术可以为一个或多个接口生成一个实现类,该实现类可以拦截接口方法的调用,并...
Java的动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。这个主题将深入探讨这两个关键组件以及与之相关的CGLIB库。 ### 1. Java动态代理 #### 1.1 Proxy类 `Proxy`...
在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类是用于创建一个代理对象,而InvocationHandler接口则定义了代理对象调用方法时的行为。 1. **...
在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。`Proxy`类用于创建代理对象,而`InvocationHandler`接口定义了处理代理对象方法调用的逻辑。 1. **...
`java.lang.reflect.Proxy` 类是用于创建动态代理对象的工厂类。我们需要使用`Proxy.newProxyInstance()`方法,传入类加载器、接口数组以及自定义的`InvocationHandler`实例,来生成代理对象。 5. **动态代理示例*...
本文将深入探讨Java中的动态代理,特别是基于`java.lang.reflect.Proxy`类的使用。 首先,`java.lang.reflect.Proxy`是Java标准库中用于生成动态代理类的关键类。它允许我们创建一个新的接口实现类,而无需手动编写...
- `Java动态代理模式.docx`可能详细讲解了动态代理模式的原理和实现,包括如何创建代理对象和实现`InvocationHandler`。 - `动态代理详解.docx`则可能深入讨论了Java动态代理的细节,包括实际应用场景和常见问题。...
JDK动态代理是通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现的。Proxy类用于创建一个代理对象,而InvocationHandler接口定义了处理代理对象方法调用的逻辑。 #### 1. 创建...
Java动态代理是Java提供的一种在运行时创建代理对象的技术,主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口组成。在这个简单的Java动态代理实例中,我们将探讨如何利用这两个核心...
在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。`Proxy` 类用于生成代理对象,而`InvocationHandler`接口定义了代理对象的方法调用应该如何处理。 ...
在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。 1. **Proxy类**: `Proxy` 类是Java提供的一个内部类,它主要用于创建一个实现了指定一组接口的...
Java中的动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。 1. **Proxy类**:Proxy是Java动态代理的核心类,它提供了创建动态代理对象的方法。代理对象是目标对象的...
### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...
Java中的`InvocationHandler`接口是Java动态代理机制的核心组成部分,主要用在`java.lang.reflect`包下。这个接口提供了一种方法,使得我们可以在运行时创建具有特定行为的代理对象。这种行为通常体现在调用代理对象...
JDK 动态代理JDK 提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来支持动态代理。Proxy 类用于创建一个代理对象,而 InvocationHandler 接口则定义了代理对象的方法调用处理逻辑。...
Java代理分为静态代理和动态代理两种。静态代理是在编译时就已经确定代理类的实现,而动态代理则是在运行时根据接口生成代理类。我们这里主要讨论的是动态代理,它基于Java的`java.lang.reflect.Proxy`类和`java....
首先,Java中的动态代理是通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现的。`Proxy`类用于创建一个代理对象,而`InvocationHandler`接口则定义了处理代理对象的方法调用的逻辑...
Java动态代理基于JDK的`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类用于创建代理类实例,而`InvocationHandler`接口定义了处理代理对象的方法调用的逻辑。 ### 2. 创建代理...