Java 使用反射生成JDK动态代理

参考资料

[1]. 疯狂Java讲义(第三版) 李刚

使用Proxy和InvocationHandler创建动态代理

Proxy提供了用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父亲。如果在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类;如果需要为一个或多个接口动态地创建实例,也可以使用Proxy来创建动态代理实例。

示例1

Person类

interface Person
{
    void walk();
    void sayHello(String name);
}

实现了InvocationHandler类的MyInvokationHandler 类,它的作用就是执行传入的类

class MyInvokationHandler implements InvocationHandler
{
    /*
    执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
    其中:
    proxy:代表动态代理对象
    method:代表正在执行的方法
    args:代表调用目标方法时传入的实参。
    */
    public Object invoke(Object proxy, Method method, Object[] args)
    {
        System.out.println("----正在执行的方法:" + method);
        if (args != null)
        {
            System.out.println("下面是执行该方法时传入的实参为:");
            for (Object val : args)
            {
                System.out.println(val);
            }
        }
        else
        {
            System.out.println("调用该方法没有实参!");
        }
        return null;
    }
}

ProxyTest类

public class ProxyTest
{
    public static void main(String[] args)
        throws Exception
    {
        // 创建一个InvocationHandler对象
        InvocationHandler handler = new MyInvokationHandler();
        // 使用指定的InvocationHandler来生成一个动态代理对象
        Person p = (Person)Proxy.newProxyInstance(Person.class.getClassLoader()
            , new Class[]{Person.class}, handler);
        // 调用动态代理对象的walk()和sayHello()方法
        p.walk();
        p.sayHello("孙悟空");
    }
}

这里写图片描述

动态代理和AOP

采用动态代理可以非常灵活的实现解耦,通常而言,使用Proxy生成一个动态代理时,往往不会凭空产生一个动态代理,这样没有太大的实际意义。通常都是为指定的目标对象生成动态代理。
这种动态代理在APO(Aspect Orient Programming,面向切面编程)中被称为APO代理,AOP代理可代替目标对象,APO代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异:APO代理里的方法可以在执行目标方法之前、之后插入一些通用处理。

示例1

public interface Dog
{
    // info方法声明
    void info();
    // run方法声明
    void run();
}
public class GunDog implements Dog
{
    // 实现info()方法,仅仅打印一个字符串
    public void info()
    {
        System.out.println("我是一只猎狗");
    }
    // 实现run()方法,仅仅打印一个字符串
    public void run()
    {
        System.out.println("我奔跑迅速");
    }
}
public class MyInvokationHandler implements InvocationHandler
{
    // 需要被代理的对象
    private Object target;
    public void setTarget(Object target)
    {
        this.target = target;
    }
    // 执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Exception
    {
        DogUtil du = new DogUtil();
        // 执行DogUtil对象中的method1。
        du.method1();
        // 以target作为主调来执行method方法
        Object result = method.invoke(target , args);
        // 执行DogUtil对象中的method2。
        du.method2();
        return result;
    }
}
public class DogUtil
{
    // 第一个拦截器方法
    public void method1()
    {
        System.out.println("=====模拟第一个通用方法=====");
    }
    // 第二个拦截器方法
    public void method2()
    {
        System.out.println("=====模拟通用方法二=====");
    }
}
public class MyProxyFactory
{
    // 为指定target生成动态代理对象
    public static Object getProxy(Object target)
            throws Exception
    {
        // 创建一个MyInvokationHandler对象
        MyInvokationHandler handler =
                new MyInvokationHandler();
        // 为MyInvokationHandler设置target对象
        handler.setTarget(target);
        // 创建、并返回一个动态代理
        return Proxy.newProxyInstance(target.getClass().getClassLoader()
                , target.getClass().getInterfaces() , handler);
    }
}

调用


public class Test
{
    public static void main(String[] args)
            throws Exception
    {
        // 创建一个原始的GunDog对象,作为target
        Dog target = new GunDog();
        // 以指定的target来创建动态代理
        Dog dog = (Dog)MyProxyFactory.getProxy(target);
        dog.info();
        dog.run();
    }
}
类图如下

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值