java代理模式与动态代理模式详解
1、代理模式
所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
生活中的例子:过年加班比较忙,没空去买火车票,这时可以打个电话到附近的票务中心,叫他们帮你买张回家的火车票,当然这会附加额外的劳务费。但要清楚票务中心自己并不卖票,只有火车站才真正卖票,票务中心卖给你的票其实是通过火车站实现的。这点很重要!
上面这个例子,你就是“客户”,票务中心就是“代理角色”,火车站是“真实角色”,卖票称为“抽象角色”!
代理模式java代码示例:
抽象角色:抽象类或接口
interface business
{
void doaction();
}
真实角色:真正实现了业务逻辑接口
代理角色:自己并未实现业务逻辑接口,而是调用真实角色来实现
class businessimplproxy implements business
{
private businessimpl bi;
public void doaction()
{
if (bi==null)
{
bi = new businessimpl();
}
dobefore();
bi.doaction();
doafter();
}
public void dobefore()
{
system.out.println("前置处理!");
}
public void doafter()
{
system.out.println("后置处理!");
}
}
//测试类
class test
{
public static void main(string[] args)
{
//引用变量定义为抽象角色类型
business bi = new businessimplproxy();
bi.doaction();
}
}
<span></span>
所以,借助于jvm的支持,可以在运行时动态生成代理类(“代理角色”),我们就可以解决上述代理模式中代码膨胀的问题,使用了动态代理后,“代理角色”将不用手动生成,而由jvm在运行时,通过指定类加载器、接口数组、调用处理程序这3个参数来动态生成。
动态代理模式java代码示例:
import java.lang.reflect.invocationhandler;
import java.lang.reflect.proxy;
import java.lang.reflect.method;
//抽象角色:java动态代理的实现目前只支持接口,不支持抽象类
interface businessfoo
{
void foo();
}
interface businessbar
{
string bar(string message);
}
//真实角色:真正实现业务逻辑方法
class businessfooimpl implements businessfoo
{
public void foo()
{
system.out.println("businessfooimpl.foo()");
}
}
class businessbarimpl implements businessbar
{
public string bar(string message)
{
system.out.println("businessbarimpl.bar()");
return message;
}
}
//动态角色:动态生成代理类
class businessimplproxy implements invocationhandler
{
private object obj;
businessimplproxy() {
}
businessimplproxy(object obj) {
this.obj = obj;
}
public object invoke(object proxy,method method,object[] args) throws throwable
{
object result = null;
dobefore();
result = method.invoke(obj,args);
doafter();
return result;
}
public void dobefore(){
system.out.println("do something before business logic");
}
public void doafter(){
system.out.println("do something after business logic");
}
public static object factory(object obj)
{
class cls = obj.getclass();
return proxy.newproxyinstance(cls.getclassloader(),cls.getinterfaces(),new businessimplproxy(obj));
}
}
//测试类
public class dynamicproxy
{
public static void main(string[] args) throws throwable
{
businessfooimpl bfoo = new businessfooimpl();
businessfoo bf = (businessfoo)businessimplproxy.factory(bfoo);
bf.foo();
system.out.println();
businessbarimpl bbar = new businessbarimpl();
businessbar bb = (businessbar)businessimplproxy.factory(bbar);
string message = bb.bar("hello,world");
system.out.println(message);
}
}
程序流程说明:
new businessfooimpl();创建一个“真实角色”,传递给工厂方法businessimplproxy.factory(),进而初始化“调用处理器”——即实现invocationhandler的类。并返回一个动态创建的代理类实例,由于“代理角色”也必然实现了“抽象角色”提供的业务逻辑方法,故可向下转型为businessbar,并赋值给指向businessbar类型的引用bb。
newproxyinstance(classloader loader, class<?>[] interfaces, invocationhandler h)方法由程序员来指定参数动态返回需要的代理类,而invoke(object proxy, method method, object[] args) 方法则是由jvm在运行时动态调用的。当执行“bb.bar("hello,world");”方法时,jvm动态指派“调用处理器”,向外层invoke传递参数,并调用method.invoke(obj,args)真正执行!
businessimplproxy.factory静态方法用来动态生成代理类(“代理角色”),在运行时根据不同的业务逻辑接口businessfoo和businessbar,在运行时分别动态生成了代理角色。“抽象角色”、“代理角色”以及调用处理器(实现invocationhandler接口的类)这三者都可以改变,所以说java的动态代理十分强大。