疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java 动态代理


 

神游:
场景一:公司老板比尔,秘书莫妮卡,任何外部电话都需要通过莫妮卡转给比尔,莫妮卡可能会答复你没预约不能与比尔通话、比尔现在忙不方便跟你通话、请你稍等马上帮你转接等。这个场景类似静态代理应用,莫妮卡是比尔的代理,任何事情找比尔都只能通过莫妮卡来转接。

场景二:张三、李四、王五都想去旅游,都去找中旅,张三想去台湾,中旅就派一个台湾导游接待张三;李四想去泰国,中旅就派一个泰国导游接待李四;王五想去新西兰,中旅就派一个新西兰导游接待王五。这个场景类似动态代理应用,中旅类似动态代理。

代理模式:
代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式的思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信。

代理模式在Java中表现为代理类与委托类实现相同的接口(Interface),代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等;而委托类才则真正实现的接口业务逻辑;客户类不能直接访问委托类,而是通过访问代理类来间接调用委托类。

Java动态代理:
Java静态代理就是编译期已经确定代理类,以及代理类中的处理逻辑;动态代理是在运行期运用Java反射机制临时生成代理类,AspectJ实现的AOP就是典型的动态代理应用。Java开发类库提供了InvocationHandler接口和Porxy类供我们使用动态代理模式。

java.lang.reflect.InvocationHandler接口:每个代理类都会绑定一个Invocation Handler,当代理类的方法被调用时,代理类就会调用handler的invoke方法进行处理。invoke方法中的参数proxy就是新生成代理类的instance,method参数是要调用的业务方法,args参数是业务方法参数。

public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

java.lang.reflect.Proxy类:动态生成的代理类的父类,提供newProxyInstance接口用于生成代理类并创建代理类instance;因为新生成的类class文件需要ClassLoader加载,所以要传入ClassLoader参数;因为代理类需要实现业务接口,所以要传入interfaces参数,这也是这种代理实现机制的特定或者说缺陷,即委托类一定要实现业务接口,定义业务接口是必要条件;因为要绑定一个handler,所以要传入h参数,或者说代理类需要调用handler的invoke方法。

/**
* the invocation handler for this proxy instance.
* @serial
*/
protected InvocationHandler h;
 
@CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

二手房代理代码示例:

package com.stevex.app.forkjoin;
 
public interface SecondhandHouse {
    public int price();
}
 
package com.stevex.app.forkjoin;
 
public class Vanke implements SecondhandHouse {
 
    public int price() {
        return 1000000;
    }
 
}
 
package com.stevex.app.forkjoin;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class ZhongyuanSecondHouse {
    public static void main(String[] args) {
        final SecondhandHouse sh = new Vanke();
 
        SecondhandHouse proxy = (SecondhandHouse) Proxy.newProxyInstance(sh
                .getClass().getClassLoader(), sh.getClass().getInterfaces(),
                new InvocationHandler() {
 
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        Object result = null;
 
                        System.out.println("签订看房合同");
                        result = method.invoke(sh, args);
                        System.out.println("缴交定金");
 
                        return result;
                    }
                });
 
        System.out.println("改二手房价格为:" + proxy.price());
    }
}