使用Proxy和InvocationHandler创建动态代理

    Proxy提供了用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。如果在程序中为一个或多个接口动态的生成实现类,
就可以使用Proxy来创建动态代理类;如果需要为一个或多个接口动态地创建实例,也可以使用Proxy来创建动态代理实例。
    Proxy提供了如下两个方法来动态创建代理类和动态代理实例。
(1)    static Class<?> getProxyClass(ClassLoder loader, Class<?>...interfaces):创建一个动态代理类多对应的Class对象,该代理类实现将实现
interfaces所指定的多个接口。第一个ClassLoader参数指定生成动态代理类的类加载器。
(2)    static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h):直接创建一个动态代理对象,该代
理对象对象的实现类实现了interfaces指定的系列接口,执行代理对象的每个方法时都会替换成执行InvocationHandler对象的invoke方法。

实际上,即使采用第一个方法生成动态代理类之后,如果程序需要通过该代理类来创建对象,依然需要传入一个Invocationhandler对象。也就
是说,系统生成的每个代理对象都有一个与之关联的Invocationhandler对象。例如下面的代码:

// 创建一个InvocationHandler对象,其中MyInvocationHandler是实现InvocationHandler接口的类
InvocationHandler handler = new MyInvocationHandler();
// 使用Proxy生成一个动态代理类proxyClass
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[]{Foo.class});
// 获取proxyClass类中带有一个InvocationHandler参数的构造器
Constructor ctor = proxyClass.getConstructor(new Class[]{Invocationhandler.class});
// 调用ctor的newInstance方法来创建动态实例
Foo f = (Foo) ctor.newInstance(new Object[]{Handler});


    下面程序示范了使用Proxy和InvocationHandler来生成动态代理对象。其目的是:对需要代理的对象的每个方法的开始和结束打印一行日志
信息:
ArithmeticCalculatorloggingImpl.java:

package com.yu.spring.aop.helloworld;

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }

}


ArithmeticCalculatorLoggingProxy.java:

package com.yu.spring.aop.helloworld;

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

public class ArithmeticCalculatorLoggingProxy {

    // 要代理的对象
    private ArithmeticCalculator target;

    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
        this.target = target;
    }

    public ArithmeticCalculator getLoggingProxy(){
        ArithmeticCalculator proxy = null;

        // 代理对象由哪一个类加载器负责加载
        ClassLoader loader = target.getClass().getClassLoader();
        // 代理对象的类型,即其中有哪些方法
        Class[] interfaces = new Class[]{ArithmeticCalculator.class};
        // 当调用代理对象其中的方法时,该执行的代码
        InvocationHandler h = new InvocationHandler(){
            /**
             * 执行动态代理对象的所有方法时,都会替换成执行如下的invoke方法,其中:
             * proxy:正在返回的代理对象,一般情况下,在invoke方法中都不使用该对象
             * method:正在被调用的方法
             * args:调用方法时,传入的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                // 日志
                System.out.println("the method " + methodName + " begins with " + Arrays.asList(args));
                // 执行方法
                Object result = method.invoke(target, args);
                // 日志
                System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));

                return result;
            }

        };

        proxy =(ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
        return proxy;
    }

}

测试类Main.java:

package com.yu.spring.aop.helloworld;

public class Main {

    public static void main(String[] args) {
//        ArithmeticCalculator ac = null;
//        ac = new ArithmeticCalculatorImpl();

        ArithmeticCalculator target = new ArithmeticCalculatorImpl();
        ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();


        int result = proxy.add(1, 2);
        System.out.println("-->" + result);

        result = proxy.sub(4, 1);
        System.out.println("-->" + result);

        result = proxy.mul(2, 3);
        System.out.println("-->" + result);

        result = proxy.div(7, 3);
        System.out.println("-->" + result);
    }
测试结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值