`

浅谈Java代理机制

阅读更多
 可以说代理是java十分重要的一种机制,另一个当然是属于反射了,jdk中单独讲到了反射API(java.lang.reflect),可能有人认为反射对资源消耗比较厉害,确实也是,反射肯定是要消耗资源的,但也不是什么都要用到反射,所以最佳试验应该是在资源消耗程度和反射的使用程度之间找到一个平衡点,本文并不打算讲反射,关于反射的心得以后再贴出来,自己最近也在折磨折磨

代理可以分为:StaticProxy 和DynamicProxy
比如:
Package xyz; 
import java.util.logging.* 
public class talkToSomebody{ 
private Logger logger=Logger.getLogger(this.getClass().getName()); 
public void talk(String name){ 
logger.log(Level.INFO,"talking start...."); 
System.out.println("Hi!ni hao,"+name); 
logger.log(Level.INFO,"talking ends...."); 
} 
} 

很显示,你需要talk其他人,其实就只有一个句话是关键的,"Hi!ni hao XXX" ,这才是需要关系的,或者叫核心业务(这个次可能有点牵强),但如果要记录你和哪些人交谈过,哪时候开始的,哪时候结束的,日志功能就是实现这个,这属于业务逻辑,把业务逻辑和核心业务放到了一起,如果哪天不需要记录了,怎么办?得重新改源代码,甚至如果客户只提供给你编译过的class或接口,你会很郁闷的!

解决方法:
用Proxy机制,其实代理就像一个中介机构,我自己突然有什么事(或者不愿意),找中介机构去做,当然你得出钱给中介机构。
public interface ITalk{ 
public void talk(String name); 
} 


可以把这个看做你的要求,中介机构必须按照你的要求来做,你才会付钱给中介机构;

public class TalkToSomebody implements ITalk{ 
public void talk(String name){ 
System.out.println("Hi,ni hao,"+name); 
} 
} 
不错,中介机构是按照我的要求实现的,结果没错!


public class StaticProxyTalk Implements ITalk{ 
private Logger logger=Logger.getLogger(this.getClass().getName()); 
private ITalk somebody; 
public StaticProxyTalk(ITalk somebody){ 
this.somebody=somebody; 
} 
public void talk(String name){ 
log("talking start...."); 
somebody.talk(name); 
log("talking ending..."); 
} 
private void log(String message){ 
logger.log(Level.INFO,message) 
} 



感觉好多了,以后我不需要中介服务了,不去找他就行,现在看下这个中介机构做得怎么样,达到我的要求了没?


public class TestProxy{ 
public static void main(String []args){ 
ITalk proxy=new StaticProxyTalk(new TalkToSomebody()); 
proxy.talk("HuYong"); 
} 
} 

是的,,它做到了,我可以付钱给它了。。

但是问题还是存在,如果我有N多事都不想自己做(比较懒),我得每一件都去找中介机构吗?能不能一类的就找一次就够了勒??

看下面的一个LogTalk:
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

/** 
* @author HuYong Email:yate7571@hotmail.com 
*/ 
public class LogTalk implements InvocationHandler { 
private Logger logger = Logger.getLogger(this.getClass().getName()); 

private Object object; 

public Object bind(Object object) { 
this.object = object; 
return Proxy.newProxyInstance(object.getClass().getClassLoader(), 
object.getClass().getInterfaces(), this); 

} 

public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable { 
Object result = null; 
try { 
log("method starts ...." + method); 
result = method.invoke(object, args); 
log("method ends...." + method); 
} catch (Exception e) { 
log(e.toString()); 
} 
return result; 
} 

private void log(String message) { 
logger.log(Level.INFO, message); 
} 

} 

只要我需要做的事是一类事(可以理解一类事物),我就可以先和中介机构签好活动,我以后所有的你帮我做就是了,我只需要结构就ok了,中介机构也承诺,只要你给我们的都符合这个约定(都是Object),我就接了。

也来测试下:
public class TestDynamicProxy{ 
public static void main(String []args){ 
LogTalk dynamicproxy=new LogTalk(); 
ITalk proxy=(ITalk)dynamicproxy.bind(new TalkToSomebody()); 
proxy.talk("YangYi"); 
} 
} 

可以通过了,,以后这些事你都可以帮我做了,我列个清单给中介机构有哪些事了,这些事你就帮我做了,如果哪天有事不需要做了,我打电话给你取消那项就可以了,不影响其他事情的继续做下去,也不需要去改动相关的约定了。。


关于LogTalk的讲解:
public static Object newProxyInstance(ClassLoader loader, 
Class<?>[] interfaces, 
InvocationHandler h) 
throws IllegalArgumentException 
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序


public Object bind(Object object) { 
this.object = object; 
return Proxy.newProxyInstance(object.getClass().getClassLoader(), 
object.getClass().getInterfaces(), this); 

绑定,只要是Object的子类就可以绑定(呵呵,所有的都是Object的子类勒!)

总结:这其实是AOP的最底层实现,AOP的的好处就是用到了代理,把各种业务逻辑分离开来了,不管是核心要处理的还是作为辅助功能(或者测试)的业务逻辑,比如日志作为一个切面可以去测试每个方法是否都执行了,用AOP就不需要去改动任何核心业务,如果不要了,就不指定Pointcut就可以了(关于AOP的各种术语可以参考 spring reference),这应该算是一种思想的转变。

补充:可能我用到的"核心业务",和其他"业务逻辑"理解有点不同,个人理解是这样的:核心业务就是我需要去关心的,这是核心。其他业务逻辑(很多书上说是与业务逻辑无关的系统服务逻辑)比如说日志,安全方面等,只是做为核心的一个外壳,没有外壳核心照样可以存活,只是没有那么美观了。
分享到:
评论
4 楼 hecongqi 2012-07-25  
谢谢,写得很好,学到知识了
3 楼 zhaomingzm_23 2009-09-17  
动态代理,实现InvocationHandler 有何用意? 覆盖的invoke function 都没用到
2 楼 benlsoft 2008-09-22  
public class TestProxy{   
public static void main(String []args){   
ITalk proxy=new StaticProxyTalk(new TalkToSomebody());   
 proxy.talk("HuYong");   
 }   
 } 

不明白ITalk proxy=new StaticProxyTalk(new TalkToSomebody());  为何要这样调用?
直接就可以这样调用:
ITalk list = new TalkToSomebody();
ITalk proxy=(ITalk)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                list.getClass().getInterfaces(),
                new TalkToSomebody<ITalk>(list));

还请楼主讲详细些。
1 楼 java1978 2008-09-02  
拜读了一下,没有全理解,不过还是很感谢,支持一下

相关推荐

    浅谈java代理机制 .txt

    ### 浅谈Java代理机制 #### 一、引言 在深入探讨Java代理机制之前,我们首先需要了解代理模式的基本概念及其应用场景。代理模式是一种结构型设计模式,它为其他对象提供了一种代理以控制对这个对象的访问。在Java...

    浅谈Java模型以外的类型策略

    在Java中,虽然其类型系统相对固定,但可以通过一些技术来扩展其灵活性,例如使用泛型、反射和动态代理等。泛型提供了一种在编译时处理类型的方式,而反射允许在运行时检查和操作类的结构,动态代理则能实现接口的...

    Java反射技术浅谈.pdf

    Java反射技术浅谈 Java作为一种广泛使用的编程语言,它的设计目标之一是提供一种灵活的编程方式,使程序能够在运行时识别和操作对象。为了实现这一目标,Java语言引入了反射机制,使得开发者能够动态地探索和操作...

    浅谈JDK动态代理与CGLIB代理去区别

    了解这两种代理机制的差异,并掌握如何在实际项目中灵活运用,能够提升我们的编程能力和解决复杂问题的能力。无论是JDK动态代理还是CGLIB代理,都是Java开发中不可或缺的工具,它们为我们的代码带来了强大的扩展性...

    java之浅谈深说--教你如何成长

    ### Java之浅谈深说——教你如何成长为Java编程高手 在IT行业中,Java作为一种广泛使用的编程语言,其重要性不言而喻。对于希望成为Java编程高手的学习者来说,掌握正确的学习路径至关重要。本文将根据提供的标题、...

    浅谈使用java实现阿里云消息队列简单封装

    浅谈使用java实现阿里云消息队列简单封装 本文主要介绍了使用Java实现阿里云消息队列的简单封装,包括对阿里云消息队列的介绍、设计方案、消息发送和接收的实现等。 一、阿里云消息队列简介 阿里云提供了两种消息...

    浅谈关于java程序员面试的一些事项

    此外,对Linux操作系统的基本命令、Shell脚本编写、Java算法、数据结构、多线程和并发处理、数据库操作、垃圾回收机制、设计模式的应用、以及加密解密和网络通信协议等知识的掌握程度,也是面试官评估的要点。...

    浅谈SOAP浅谈SOAP

    ### 浅谈SOAP #### 一、引言 随着信息技术的迅速发展,现代企业的运营环境变得日益复杂。这种复杂性不仅体现在技术层面,更表现在跨平台、跨系统的集成需求上。为了应对这一挑战,企业解决方案必须具备广泛的兼容...

    浅谈Android开发系列网络篇之Retrofit

    2. **动态代理机制**: Retrofit通过Java的动态代理技术,将我们定义的接口转化为实际的网络请求执行者。我们只需要创建一个接口,定义我们需要的网络请求方法,然后通过`RestAdapter`实例化该接口的实现类,即可...

    浅谈BeanPostProcessor加载次序及其对Bean造成的影响分析

    在Spring框架中,BeanPostProcessor(BPP)是一个至关重要的组件,它允许开发者在Spring容器创建Bean实例之后和初始...通过精细的配置和合理的依赖管理,我们可以充分利用Spring的这种机制,实现高度定制化的Bean行为。

    漫谈设计模式代码

    代理模式的代码实现可能包括静态代理和动态代理(如Java的`java.lang.reflect.Proxy`)。 6. **观察者模式**:定义对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新...

    2020年百度、阿里、腾讯、字节跳动Android高频面试题解析.pdf

    首先,Java 基础部分深入浅出地介绍了数据类型,包括基本数据类型(如整型、浮点型、字符型和布尔型)以及引用数据类型。String 类是面试中常见的重点,涉及到字符串的创建、拼接、比较和不可变性等特性。运算章节...

    springCloud系统学习

    8. **微服务开发框架浅谈** - 常见的微服务开发框架包括Spring Cloud、Dubbo、Kubernetes等。 #### 二、服务发现与注册 1. **服务注册** - 当服务启动时,将其网络地址注册到服务注册表中,以便其他服务能够找到...

Global site tag (gtag.js) - Google Analytics