如果创建一个对象需要花费较多的时间,做较多的工作,同时还不确定后面会不会实际用上,如你在超市买手机,就给一个模型给你看就得了,你确定要的时候才去拿一个真机器来给你,这里这个手机模型可以看作是手机的一个代理。还有现在的艺人都会有经纪人,大部分事情你跟他的经纪人联系就搞定了,在登台演出的时候,经纪人自然会安排艺人Live Show。这里经纪人就是艺人的一个Proxy。同时在Proxy这里还可以做一个权限控制,做一层过滤,如在经纪人这里,看你拿不出100W,根本就不会安排艺人演出,艺人也根本就不知道你这个事情,在打印机那里,在打印的时候,也可以做一个权限控制,只有在你具有打印机的操作权限时才会让你打印。权限验证没有通过,打印机对象根本就不会生成。JLive的Forum就使用Proxy进行了权限控制。
打印机程序实例,在真正需要打印的时候才生成打印机对象:
/**
*
@(#)Printable.java
1.0
2007
-
10
-
23
*/
package
pattern.proxy;
/**
*
@author
tsimgsong
*
*/
public
interface
Printable {
/**
*
Name
printer
*
@param
name
*/
public
void
setPrinterName(String name);
/**
*
get
Printer
Name
*
@return
*/
public
String getPrinterName();
/**
*print
content
*
@param
cnt
*/
public
void
print(String cnt);
}
/**
* @(#)Printer.java 1.0 2007-10-23
*/
package pattern.proxy;
import org.apache.log4j.Logger;
/**
* @author tsimgsong
*
*/
public class Printer implements Printable {
private String name;
static Logger logger = Logger.getLogger(Printer.class);
public Printer(){
logger.info("Initializing Printer begin ...");
logger.info("Initialize Printer end ");
}
public Printer(String name){
this.name = name;
}
public String getPrinterName() {
return name;
}
public void print(String cnt) {
logger.info("Print Begin");
logger.info("Print End");
}
public void setPrinterName(String name) {
this.name = name;
}
}
/**
* @(#)PrinterProxy.java 1.0 2007-10-23
*/
package pattern.proxy;
/**
* @author tsimgsong
*
*/
public class PrinterProxy implements Printable {
private String name ;
private Printer printer;
public PrinterProxy(){
}
public PrinterProxy(String name){
this.name = name;
}
public String getPrinterName() {
return name;
}
public void print(String cnt) {
realPrinter();
printer.print(cnt);
}
public synchronized void setPrinterName(String name) {
if(printer != null){
printer.setPrinterName(name);
}
this.name = name;
}
private synchronized void realPrinter(){
if(printer == null){
printer = new Printer(name);
}
}
}
如对打印机的使用进行权限控制,就不要客户端直接生成Printer对象,要打印都通过PrinterProxy来打印,在打印的地方对客户端权限进行判定。
public void print(PrintPermission permission,String cnt) throws PrintException,
UnauthorizedException {
if(permission.canPrint()){
realPrinter();
printer.print(cnt);
}else{
Throw new
UnauthorizedException();
}
}
使用Java提供的动态代理:(JAVA提供了一个Proxy类和一个InvocationHandler,这两个类都在java.lang.reflect包中。程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行方法,方法被调用的同时,执行处理器会被自动调用。)
package
pattern.proxy;
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.lang.reflect.Proxy;
/**
*
@author
tsimgsong
*
*/
public
class
DynamicProxy
implements
InvocationHandler{
private
Object
original
;
public
DynamicProxy(Object orig){
this
.
original
= orig;
}
public
Object invoke(Object proxy, Method method, Object[] args)
throws
Throwable {
//
这里可以加上权限控制
Object obj = method.invoke(
original
, args);
return
obj;
}
public
static
void
main(String args[]){
Printer pp =
new
Printer();
DynamicProxy dp =
new
DynamicProxy(pp);
Printable p = (Printable)Proxy.newProxyInstance(DynamicProxy.
class
.getClassLoader(),
new
Class[]{Printable.
class
}, dp);
p.print(
"ddddd"
); }
}
程序首先创建一个被代理对象然后初始化代理对象,最后由Proxy的newProxyInstance获得一个代理实例, newProxyInstance方法有三个参数, ClassLoader, Class[] interfaces, InvocationHandler。ClassLoader是当前的类加载器,interfaces是代理实例要实现的接口的类(需要指出java的Proxy是针对接口的,如果传入的Class类型不是接口,会抛出IllegalArgumentException异常)。InvocationHandler则是我们写的代理处理器。newProxyInstance获得的实例对象的类是通过修改java二进制文件来获得的,Proxy中有一个private static native Class defineClass0(ClassLoader loader, String name,byte[] b, int off, int len);方法,这个本地方法实现了这个Class的生成,至于具体的实现我们无法看到,不过很多资料上都有关于native方法的讨论。
Ref:
2、 http://boool.blogdriver.com/boool/284115.html