一、我们先来看线静态代理
- 静态代理的使用
先看一段代码
public class Debug {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject(); //1.创建委托对象
RealSubjectProxy r = new RealSubjectProxy(realSubject);
r.request();
}
}
/**
* 接口
*/
interface Subject{
void request();
void request_once();
}
/**
* 委托类
*/
class RealSubject implements Subject{
public void request(){
System.out.println("====RealSubject Request====");
}
public void request_once(){
System.out.println("====RealSubject Request_once====");
}
}
/**
*代理类
*/
class RealSubjectProxy implements Subject{
private Subject s = null;
public RealSubjectProxy(Subject s){
this.s = s;
}
public void request(){
System.out.println("====RealSubjectProxy Request====");
s.request();
}
public void request_once(){
System.out.println("====RealSubjectProxy Request_once====");
s.request_once();
}
}
看下执行结果
====RealSubjectProxy Request====
====RealSubject Request====
我们在看下源文件目录里的文件
在
javac Debug.java
的过程中生成了我们在Debug.java中声明的几个类的class文件,所谓静态代理就是这个意思,在编辑过程中生成了class文件。
执行结果说明通过静态代理,我们可以给委托类的方法进行扩展。
- 静态代理的缺点
对于想扩展的所有方法都需要实现一次,代码相对臃肿很多。
二、动态代理
- 动态代理的使用
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject(); //1.创建委托对象
ProxyHandler handler = new ProxyHandler(realSubject); //2.创建调用处理器对象
Subject proxySubject = (Subject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(),
RealSubject.class.getInterfaces(), handler); //3.动态生成代理对象
proxySubject.request(); //4.通过代理对象调用方法
proxySubject.request_once(); //4.通过代理对象调用方法
}
}
/**
* 接口
*/
interface Subject{
void request();
void request_once();
}
/**
* 委托类
*/
class RealSubject implements Subject{
public void request(){
System.out.println("====RealSubject Request====");
}
public void request_once(){
System.out.println("====RealSubject Request_once====");
}
}
/**
* 代理类的调用处理器
*/
class ProxyHandler implements InvocationHandler{
private Subject subject;
public ProxyHandler(Subject subject){
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("proxy.class="+proxy.getClass().getInterfaces()[0]);
System.out.println("====before====");//定义预处理的工作,当然你也可以根据 method 的不同进行不同的预处理工作
Object result = method.invoke(subject, args);
System.out.println("====after====");
return result;
}
}
我们来看下执行结果
====before====
====RealSubject Request====
====after====
====before====
====RealSubject Request_once====
====after====
我们稍微改下代码,如下:
/**
* 代理类的调用处理器
*/
/**
* 代理类的调用处理器
*/
class ProxyHandler implements InvocationHandler{
private Subject subject;
public ProxyHandler(Subject subject){
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("proxy.superclass="+proxy.getClass().getSuperclass().getName());
System.out.println("proxy.class="+proxy.getClass().getName());
System.out.println("proxy.interfaces="+proxy.getClass().getInterfaces()[0]);
System.out.println("====before====");//定义预处理的工作,当然你也可以根据 method 的不同进行不同的预处理工作
Object result = method.invoke(subject, args);
System.out.println("====after====");
return result;
}
}
我们再看下执行结果
proxy.superclass=java.lang.reflect.Proxy
proxy.class=$Proxy0
proxy.interfaces=interface Subject
====before====
====RealSubject Request====
====after====
proxy.superclass=java.lang.reflect.Proxy
proxy.class=$Proxy0
proxy.interfaces=interface Subject
====before====
====RealSubject Request_once====
====after====
我们看到 ,proxy对象是类$Proxy0的一个实例,但是我们在Test.java所在目录下并没有看到相关的.class文件
那是因为这个类是运行中生成的。我们还可以看到这个类还实现了接口Subject。
那动态代理是如何实现调用接口类的方法,都先会调用InvocationHandler的invoke方法呢?
先来看一段为代码
public final class $Proxy0 extends Proxy implements Subject {
void request(){
Method m = Class.forName("xx.Subject").getMethod("request", new Class[0]);
super.h.invoke(this,m,(Object[])null);
}
}
这里的h是什么呢?我们知道$Proxy0是继承自Proxy对象的,显然h应该是来自父类的成员变量。我们看线Proxy的源代码
231public class Proxy implements java.io.Serializable {
232
233 private static final long serialVersionUID = -2222568056686623797L;
234
235 /** prefix for all proxy class names */
236 private final static String proxyClassNamePrefix = "$Proxy";
237
238 /** parameter types of a proxy class constructor */
239 private final static Class[] constructorParams =
240 { InvocationHandler.class };
241
242 /** maps a class loader to the proxy class cache for that loader */
243 private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
244 = new WeakHashMap<>();
245
246 /** marks that a particular proxy class is currently being generated */
247 private static Object pendingGenerationMarker = new Object();
248
249 /** next number to use for generation of unique proxy class names */
250 private static long nextUniqueNumber = 0;
251 private static Object nextUniqueNumberLock = new Object();
252
253 /** set of all generated proxy classes, for isProxyClass implementation */
254 private static Map<Class<?>, Void> proxyClasses =
255 Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
256
257 /**
258 * the invocation handler for this proxy instance.
259 * @serial
260 */
261 protected InvocationHandler h;
我们看到了这个成员变量
261 protected InvocationHandler h;
就是我们传进去的ProxyHandler。以上就解释了为什么代理对象在调用接口方法时,都会先点用InvokeHandler的invoke方法了。