java动态代理

代理模式最主要的是有一个公共接口(person),一个具体实现类(student),一个代理类(studentProxy)。代理类持有具体类的实例,代为执行具体类的实例方法。

使用代理模式的一个很大的优点。最直白的就是在Spring中的面向切面编程(AOP),我们能在一个切点之前执行一些操作,在一个切点之后执行一些操作,这个切点就是一个个方法。这些方法所在类肯定就是被代理了,在代理过程中切入了一些其他操作。

1.动态代理

代理类在程序运行时创建的代理的方式为动态代理,在静态代理模式中,代理类是事先定义好的,在程序运行之前就已经编译好的,然而动态代理是在程序运行时根据java代码的“指示”动态生成的,相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的方法。

 

动态代理的简单实现

在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。

/**
 * 创建Person接口
 * @author Gonjan
 */

public interface Person {
    //上交班费
    void giveMoney();
}

public class Student implements Person {
    private String name;
    public Student(String name) {
        this.name = name;
    }    
    @Override
    public void giveMoney() {
        try {
          //假设数钱花了一秒时间
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
       System.out.println(name + "上交班费50元");
    }
}

public class MonitorUtil {
    private static ThreadLocal<Long> tl = new ThreadLocal<>();
    public static void start() {
        tl.set(System.currentTimeMillis());
    }    
    //结束时打印耗时
    public static void finish(String methodName) {
        long finishTime = System.currentTimeMillis();
        System.out.println(methodName + "方法耗时" + (finishTime - tl.get()) + "ms");
    }
}

public class StuInvocationHandler<T> implements InvocationHandler {
   //invocationHandler持有的被代理对象
    T target;
    public StuInvocationHandler(T target) {
       this.target = target;
    }  
    /**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");
     */   
        //代理过程中插入监测方法,计算该方法耗时
        MonitorUtil.start();
        Object result = method.invoke(target, args);
        MonitorUtil.finish(method.getName());
        return result;
    }
}

public class ProxyTest {
    public static void main(String[] args) {
        //创建一个实例对象,这个对象是被代理的对象
        Person zhangsan = new Student("张三");
        //创建一个与代理对象相关联的InvocationHandler
        InvocationHandler stuHandler = new StuInvocationHandler<Person>(zhangsan);
        //创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
        Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);

 //代理执行上交班费的方法
        stuProxy.giveMoney();
    }
}

我们执行这个ProxyTest方法,创建了一个需要代理的对象student,把对象zhangsan作为参数传给了StuInvocationHandler,上面说到所有被代理对象的方法都会被替换成invoke方法,所以看到一下结果。

代理类的优势在于很方便的对代理类的函数进行统一处理,而不用修改每个代理类中的方法,因为所有被代理类中的

方法都会换成InvocationHandler中的invoke方法,所以只需要在invoke方法中统一处理,就可以对所有被代理对象的方法进行相同的操作。

详情点击链接https://www.cnblogs.com/gonjan-blog/p/6685611.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值