1.定义一个接口A
2.定义一个实现类B
3.定义一个类C,实现InvocationHandler接口【持有B】
4.调用Proxy.newProxyInstance 【参数为A,C】
5.从4得到一个最终的代理对象D
这里解释一下InvocationHandler里面的invoke方法的第一个参数是什么,这里直接贴出代码,省得再去翻看。
先来看看最终生成的关系图:
对上图进行解释:
我们最终调用的是
Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy)
最后一个参数便是InvocationHandler的实现类,可以看到,这个实现类是由我们来实例化的,也就是说我们可以把被代理对象实例化之后,通过构造方法存放进去(也可以通过其他办法),然后在invoke被调用的时候,怎么去调用被代理对象,就是用户自己的事情了。
看看代码:
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;
}
}
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);
}
}
代码参考:https://blog.csdn.net/jiankunking/article/details/52143504#三、JDK的动态代理怎么使用?