java动态代理

来源:互联网 发布:java 多泛型 编辑:程序博客网 时间:2024/06/07 05:26

一 .代理模式

代理模式(Proxy Pattern)是GoF 23种Java常用设计模式之一。使用代理模式创建代理对象,让代理对象控制目标对象的访问(目标对象可以是远程的对象、创建开销大的对象或需要安全控制的对象),并且可以在不改变目标对象的情况下添加一些额外的功能。

Subject:抽象主题角色,抽象主题类可以是抽象类,也可以是接口,是一个最普通的业务类型定义,无特殊要求。
RealSubject:具体主题角色,也叫被委托角色、被代理角色。是业务逻辑的具体执行者。
Proxy:代理主题角色,也叫委托类、代理类。它把所有抽象主题类定义的方法给具体主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后工作。

Subject,抽象接口:

public interface HelloWord {    public void sayHello(int i);    public void sayHello1();}

RealSubject,具体实现:

public class HelleWordImpl implements HelloWord {    @Override    public void sayHello(int i) {        // TODO Auto-generated method stub        System.out.println("HelloWord!!!"+i);    }    @Override    public void sayHello1() {        // TODO Auto-generated method stub        System.out.println("HelloWord!!!afad");    }}

Proxy,代理类:

public class proxyDemo implements HelloWord{    private HelloWord helloWord;    public proxyDemo(HelloWord helloWord) {        // TODO Auto-generated constructor stub        this.helloWord = helloWord;    }    @Override    public void sayHello(int i) {        // TODO Auto-generated method stub        System.out.println("pre");        helloWord.sayHello(i);    }    @Override    public void sayHello1() {        // TODO Auto-generated method stub        System.out.println("pre");        helloWord.sayHello1();    }}

Client,客户端:

public class client{    public static void main(String[] args) {        // TODO Auto-generated method stub        HelloWord hw = new HelleWordImpl();        proxyDemo proxy = new proxyDemo(hw);        proxy.sayHello1();    }}

运行结果:
pre
HelloWord!!!afad

运用场景:
在我们程序设计中也可使用代理模式来将由一系列无关逻辑组合在一起的代码进行解耦合,比如业务代码中的日志代码就可以在代理中进行。Spring的AOP就是典型的动态代理应用。

二.java动态代理

java动态代理是指,在运行程序之前,代理类并不存在,可以通过java反射机制动态生成。java动态代理类在java.lang.reflect下面,主要包括InvocationHandler和Proxy。
Proxy:创建动态代理类。
InvocationHandler:处理接口方法的调用转发。

Subject类及实现同上,代理处理类HelloWordHandler ,
该类实现了Java反射包中的InvocationHandler接口。代理实例调用方法时,将对方法调用指派到它的代理处理器程序的invoke方法中。invoke方法内部实现预处理,对委托类方法调用,事后处理等逻辑:

public class HelloWordHandler implements InvocationHandler {    private Object obj;    public HelloWordHandler(Object obj) {        // TODO Auto-generated constructor stub        this.obj = obj;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        // TODO Auto-generated method stub        System.out.println("pre!!!");        //java反射机制,反射执行某个类的某个方法        method.invoke(obj, args);        System.out.println("after!!!");        return null;    }}

client:

public class client {    public static void main(String[] args) {        // TODO Auto-generated method stub        HelloWord hw = new HelleWordImpl();        ////代理实例的调用处理程序。         InvocationHandler handle = new HelloWordHandler(hw);        //使用Java反射机制中的Proxy.newProxyInstance方式创建一个代理类实例,        //要指定该实例的类加载器,需要实现的接口(即目标接口),以及处理代理实例接口调用的处理器。        HelloWord proxy = (HelloWord) Proxy.newProxyInstance(hw.getClass().getClassLoader(),                 hw.getClass().getInterfaces(), handle);        proxy.sayHello(1);    }}

最后,调用代理类目标接口方法时,会自动将其转发到代理处理器中的invoke方法内,invoke方法内部实现预处理,对委托类方法调用,事后处理等逻辑。

创建一个典型的动态代理创建对象过程可分为以下四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))

0 0
原创粉丝点击