`

浅谈Java代理机制反射

    博客分类:
  • Java
 
阅读更多
反射例子http://panyongzheng.iteye.com/blog/1326107

java静态代理和动态代理 http://blog.csdn.net/giserstone/article/details/17199755
代理概念
为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信。

静态代理
由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。




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

代理可以分为:StaticProxy 和DynamicProxy
比如:   
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),这应该算是一种思想的转变。

补充:可能我用到的"核心业务",和其他"业务逻辑"理解有点不同,个人理解是这样的:核心业务就是我需要去关心的,这是核心。其他业务逻辑(很多书上说是与业务逻辑无关的系统服务逻辑)比如说日志,安全方面等,只是做为核心的一个外壳,没有外壳核心照样可以存活,只是没有那么美观了。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics