实现jdk动态代理和CGLIB动态代理

JDK自带方法

首先介绍一下最核心的一个接口和一个方法:

首先是java.lang.reflect包里的InvocationHandler接口:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

我们对于被代理的类的操作都会由该接口中的invoke方法实现,其中的参数的含义分别是:

  • proxy:被代理的类的实例
  • method:调用被代理的类的方法
  • args:该方法需要的参数

使用方法首先是需要实现该接口,并且我们可以在invoke方法中调用被代理类的方法并获得返回值,自然也可以在调用该方法的前后去做一些额外的事情,从而实现动态代理,下面的例子会详细写到。

另外一个很重要的静态方法是java.lang.reflect包中的Proxy类的newProxyInstance方法:

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

其中的参数含义如下:

  • loader:被代理的类的类加载器
  • interfaces:被代理类的接口数组
  • invocationHandler:就是刚刚介绍的调用处理器类的对象实例 

该方法会返回一个被修改过的类的实例,从而可以自由的调用该实例的方法。下面是一个实际例子。

接口:

public interface Person {
    void show();

    void dance();
}

被代理类:

public class User implements Person, A {
    private int id;
    private String name;
    private String password;

    public void show() {
        System.out.println("User show______");
    }

    public void dance() {
        System.out.println("dance____");
    }
}

生成代理:

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

public class MyJdkAgent {

    static class MyHandler implements InvocationHandler {
        private Object proxy;

        public MyHandler(Object proxy) {
            this.proxy = proxy;
        }

        /**
         *
         * @param proxy 被代理类实例
         * @param method 调用被代理的类的方法
         * @param args 该方法所需要的参数
         * @return
         * @throws Throwable
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("hehe");
            Object res = method.invoke(this.proxy, args);
            System.out.println("haha");
            return res;
        }
    }

    /**
     *
     * @param beProxied 被代理类
     * @param interfaces 被代理类的接口数组
     * @param proxy 被代理类的实例
     * @return
     */
    public static Object getAgent(Class beProxied, Class[] interfaces, Object proxy) {
        /**
         * 参数分别是(被代理类加载器,被代理类接口数组,处理器类的对象)
         */
        return Proxy.newProxyInstance(beProxied.getClassLoader(), interfaces, new MyHandler(proxy));
    }
}

测试:

        Person person = (Person) MyJdkAgent.getAgent(User.class, new Class[]{Person.class}, new User());
        person.dance();

 结果:

hehe
dance____
haha

CGLIB动态代理

被代理类:

public class Car {
    private int id;
    private User owner;

    public void display() {
        System.out.println("dididi....");
    }
}

生成代理对象类:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyCglibAgent implements MethodInterceptor {

    private Object proxy;

    /**
     *
     * @param proxy 被代理类
     * @return 代理对象
     */
    public Object getInstance(Object proxy) {
        this.proxy = proxy;
        Enhancer enhancer = new Enhancer();
//        设置父类
        enhancer.setSuperclass(this.proxy.getClass());
//        设置enhancer回调对象
        enhancer.setCallback(this);
//        创建代理对象
        return enhancer.create();
    }

    /**
     *
     * @param o 生成的代理对象
     * @param method 被代理对象方法
     * @param objects 方法参数
     * @param methodProxy 代理方法
     * @return
     * @throws Throwable
     */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before__________");
        Object ret = methodProxy.invokeSuper(o, objects);
        System.out.println("after____________");
        return ret;
    }
}

测试:

        MyCglibAgent myCglibAgent = new MyCglibAgent();
        Car car = (Car) myCglibAgent.getInstance(new Car());
        car.display();

结果:

before__________
dididi....
after____________

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值