JDK动态代理的实现原理
1、在JDK的java.lang.reflect包下有个Proxy类,他正是构造代理类的入口。
2、该类有一个方法newProxyInstance就是创建代理对象的方法。
3、这个方法需要3个参数:
- ClassLoader,用来加载代理类的Loader类,通常这个Loader和被代理的类是同一个Loader类;
- Interfaces,是要被代理的那些接口;
- InvocationHandler,用于执行除了被代理接口中方法之外的用户自定义的操作,他也是用户需要代理的最终目的。用户调用目标方法都被代理到在InvocationHandler类中定义的唯一方法invoke()中。
4、下面开始贴代码
package com.hl.chapter11.demo;
/**
* 需要动态代理的接口
*/
public interface Target {
/**
* 你好
*
* @param name
* @return
*/
public String SayHello(String name);
/**
* 再见
*
* @return
*/
public String SayGoodBye();
}
package com.hl.chapter11.demo;
/**
* 需要动态代理的实际对象
*/
public class RealTarget implements Target {
@Override
public String SayHello(String name) {
return "Hello " + name;
}
@Override
public String SayGoodBye() {
return "Good Bye";
}
}
package com.hl.chapter11.demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 调用处理器实现类
* 每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象
*/
public class MyInvocationHandler implements InvocationHandler {
/**
* 这个是我们代理的真实对象
*/
private Object object;
/**
* 构造方法,给我们要代理的真实对象赋初值
*
* @param object
*/
public MyInvocationHandler(Object object) {
this.object = object;
}
/**
* 该方法负责集中处理动态代理类上的所有方法调用
* 动态代理类根据这三个参数进行预处理或分派到委托类实例上反射执行
*
* @param proxy 代理类实例
* @param method 被调用的方法对象
* @param args 调用参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代理真实对象前的自定义操作
System.out.println("----------------代理真实对象前的自定义操作------------------");
System.out.println("Method: " + method);
// 当代理对象调用真实对象的方法时,其会自动跳转到代理对象关联的handler对象的invoke方法进行调用
Object returnObject = method.invoke(object, args);
// 代理真实对象后的自定义操作,此处为代理的最终目的
System.out.println("---------------代理真实对象后自定义操作-----------------");
return returnObject;
}
}
package com.hl.chapter11.demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* jdk动态代理演示
*/
public class JdkDynamicProxyTest {
public static void main(String[] args) {
// 代理的真实对象
Target realTarget = new RealTarget();
/**
* MyInvocationHandler 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
* 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用.
* 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
*/
InvocationHandler handler = new MyInvocationHandler(realTarget);
// 获取类加载器
ClassLoader classLoader = realTarget.getClass().getClassLoader();
// 获取真实对象所实现的接口
Class[] interfaces = realTarget.getClass().getInterfaces();
/**
* 该方法用户指定类加载器、一组接口、调用处理器来生成动态代理类实例
*/
Target target = (Target) Proxy.newProxyInstance(classLoader, interfaces, handler);
System.out.println("动态代理对象的类型:" + target.getClass().getName());
String hello = target.SayHello("World");
System.out.println(hello);
String goodbye = target.SayGoodBye();
System.out.println(goodbye);
}
}
5、执行结果如下:
动态代理对象的类型:com.sun.proxy.$Proxy0
----------------代理真实对象前的自定义操作------------------
Method: public abstract java.lang.String com.hl.chapter11.demo.Target.SayHello(java.lang.String)
---------------代理真实对象后自定义操作-----------------
Hello World
----------------代理真实对象前的自定义操作------------------
Method: public abstract java.lang.String com.hl.chapter11.demo.Target.SayGoodBye()
---------------代理真实对象后自定义操作-----------------
Good Bye
Process finished with exit code 0
还没有评论,来说两句吧...