设计模式——动态代理

    之前讲过,静态代理的两个缺点:1. 需要手动建立代理类,当需要代理的对象增多时,会创建多个代理类 2. 代理与被代理对象实现同一接口,对象间耦合度太高。那么动态代理是如何解决这两个问题的呢?

 

1. 动态代理简介:


首先先说个结论,动态代理主要是通过反射机制动态创建的。

JDK的reflect包中提供了Proxy类来获得动态代理,Proxy类中有一个非常重要的方法Proxy.newProxyInstance:

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException{...}

Proxy.newProxyInstance的参数介绍:

-ClassLoader loader:被代理类的类加载器,其实我感觉(包括也是《大话设计模式》一书作者的想法)这个参数没啥用,因为传入的总是被代理对象的类加载器啊。。。

-Class<?>[] interfaces:被代理类的接口。 可以选择性地代理接口。

-InvocationHandler h:InvocationHandler的实现类。这是实现动态代理最重要的一个类

 

2. InvocationHandler及具体代码实现(仍以Business这个接口为例)


package designpatterns.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by Olive on 2017/9/11.
 * 动态代理:运用反射机制动态创建而成
 */
public class BusinessDynamicProxyHandler implements InvocationHandler {

    // 被代理的对象
    private Object object;

    public BusinessDynamicProxyHandler(Object object){
        this.object = object;
    }

    // proxy指代理类,method指被代理的方法,args指方法的参数数组
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        String methodName = method.getName();
        if(methodName.equals("transaction")){
            System.out.println("start process a transaction");
        }
        // 去调用被代理对象的方法
        Object result = method.invoke(object, args);

        return result;
    }

    // 生成代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }
}


InvocationHandler接口中只有一个方法invoke:

 

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

invoke方法的参数介绍:

- Objectproxy:指代理对象,其实这个参数在方法中根本没用到,不知道干嘛要暴露出来。。。

- Methodmethod:被代理的方法

- Object[]args:代理方法的参数

 

3. 跑下测试用例:


package designpatterns.proxy;

import java.lang.reflect.Field;

/**
 * Created by Olive on 2017/9/11.
 */
public class ProxyDynamicTest {

    public static void main(String[] args){

        CarBusiness carBusiness = new CarBusiness();
        BusinessDynamicProxyHandler proxyHandler = new BusinessDynamicProxyHandler(carBusiness);
        // 获得代理,可以发现代理并不需要实现Business接口,所以之后接口的修改并不会影响代理类的实现
        // 所以完成了解耦
        Business businessProxy = (Business) proxyHandler.getProxy();
        // 调用代理方法,实际通过调用invoke方法来执行相应的方法
        businessProxy.transaction();
    }

}


然后看下结果:


start process a transaction
I want to buy a car!


4. 一点小总结:


开头说过静态代理的缺点,可以看到,动态代理比较好地解决了手动创建代理的问题。并且,我们看到代理类和被代理类不需要实现同一个接口,这些修改原接口只会影响到被代理类,类之间的耦合度降低了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值