signed

QiShunwang

“诚信为本、客户至上”

动态代理

2021/3/21 10:06:51   来源:

jdk动态代理是面向接口的代理,首先我们要写一个接口,里面放着需要代理的方法,然后写一个具体的实现类,这个实现类就是需要代理的具体对象,接下来要写一个public class InvocationHandlerImpl implements InvocationHandle,这个类实现了invocationhandle接口,首先我们要传一个具体的代理对象进去,然后实现了invocationhandler这个接口的都要实现一个invoke方法,在这个方法里,我们需要实现被代理对象的具体方法,然后可以在之前和之后实现一个before和after的方法,这个就是需要代理的东西。

package jiankunking;
 
/**
 * 需要动态代理的接口
 */
public interface Subject
{
    /**
     * 你好
     *
     * @param name
     * @return
     */
    public String SayHello(String name);
 
    /**
     * 再见
     *
     * @return
     */
    public String SayGoodBye();
}
package jiankunking;
 
/**
 * 被代理的实际对象
 */
public class RealSubject implements Subject
{
 
    /**
     * 你好
     *
     * @param name
     * @return
     */
    public String SayHello(String name)
    {
        return "hello " + name;
    }
 
    /**
     * 再见
     *
     * @return
     */
    public String SayGoodBye()
    {
        return " good bye ";
    }
}
package jiankunking;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
 
/**
 * 调用处理器实现类
 * 每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象
 */
public class InvocationHandlerImpl implements InvocationHandler
{
 
    /**
     * 这个就是我们要代理的真实对象
     */
    private Object subject;
 
    /**
     * 构造方法,给我们要代理的真实对象赋初值
     *
     * @param subject
     */
    public InvocationHandlerImpl(Object subject)
    {
        this.subject = subject;
    }
 
    /**
     * 该方法负责集中处理动态代理类上的所有方法调用。
     * 调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
     *
     * @param proxy  代理类实例
     * @param method 被调用的方法对象
     * @param args   调用参数
     * @return
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        //在代理真实对象前我们可以添加一些自己的操作
        System.out.println("在调用之前,我要干点啥呢?");
 
        System.out.println("Method:" + method);
 
        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        Object returnValue = method.invoke(subject, args);
 
        //在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("在调用之后,我要干点啥呢?");
 
        return returnValue;
    }
}

下面是具体实现,首先获得一个需要代理的对象,然后获得他的method和classloader,接下来生成一个实现了invocationhandler接口的invocationhandlerimp,将需要代理的对象传进去,传进去之后通过Proxy的new instance 方法生成一个具体的代理类,

package jiankunking;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
 
/**
 * 动态代理演示
 */
public class DynamicProxyDemonstration
{
    public static void main(String[] args)
    {
        //代理的真实对象
        Subject realSubject = new RealSubject();
        
        /**
         * InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
         * 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用.
         * 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
         */
        InvocationHandler handler = new InvocationHandlerImpl(realSubject);
 
        ClassLoader loader = realSubject.getClass().getClassLoader();
        Class[] interfaces = realSubject.getClass().getInterfaces();
        /**
         * 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
         */
        Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
 
        System.out.println("动态代理对象的类型:"+subject.getClass().getName());
 
        String hello = subject.SayHello("jiankunking");
        System.out.println(hello);
//        String goodbye = subject.SayGoodBye();
//        System.out.println(goodbye);
    }
 
}