如有轉(zhuǎn)載請注明出處http://www.reibang.com/p/bc478bc46515
緒論
java中的代理分為靜態(tài)代理和動態(tài)代理轨功,靜態(tài)代理使用于同一類型的群體的代理,而動態(tài)代理適用于不同群體之間的代理膳叨,靜態(tài)代理在編譯器就已經(jīng)存在了,并且編譯成class文件史辙,在我看來代理可以用來增強(qiáng)功能土童。
靜態(tài)代理
舉個例子說明同辣,一看就知道什么是靜態(tài)代理了
package a.h;
public interface Person {
void eat();
}
package a.h;
public class Adult implements Person{
@Override
public void eat() {
System.out.println("吃西虹市炒雞蛋");
}
}
package a.h;
public class Baby implements Person{
@Override
public void eat() {
System.out.println("吃輔食");
}
}
package a.h;
public class StaticPersonProxy implements Person{
private Person p;
public StaticPersonProxy(Person p){
this.p=p;
}
@Override
public void eat() {
System.out.println("把飯盛碗里");
System.out.println("坐在凳子上");
p.eat();
System.out.println("洗碗");
}
}
package a.h;
public class StaticPersonTest {
public static void main(String[] args) {
Person adult = new Adult();
StaticPersonProxy adultProxy = new StaticPersonProxy(adult);
adultProxy.eat();
System.out.println("---------------------");
Person baby =new Baby();
StaticPersonProxy babyProxy = new StaticPersonProxy(baby);
babyProxy.eat();
}
}
運(yùn)行結(jié)果:
把飯盛碗里
坐在凳子上
吃西虹市炒雞蛋
洗碗
---------------------
把飯盛碗里
坐在凳子上
吃輔食
洗碗
上面的例子可以看出這個代理類只能代理Person群體,如果想代理佳通工具或者水果等需要在定義自己的代理類匀们。
動態(tài)代理
package a.i;
public interface HouseInterface {
void bed();
}
package a.i;
public class Home implements HouseInterface{
public void bed(){
System.out.println("家里的床");
}
}
package a.i;
public interface TrafficInteface {
void hardBed();
}
package a.i;
public class Train implements TrafficInteface{
public void hardBed(){
System.out.println("火車硬臥");
}
}
package a.i;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynProxy implements InvocationHandler {
private Object o;
public DynProxy(Object o){
this.o=o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("脫了鞋");
System.out.print("躺在");
method.invoke(o,args);
System.out.println("--------------");
return null;
}
}
package a.i;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.Properties;
public class DynProxyTest {
public static void main(String[] args) {
try {
generatedProxyFiles();
HouseInterface house = new Home();
DynProxy dynProxy = new DynProxy(house);
HouseInterface h = (HouseInterface) Proxy.newProxyInstance(house.getClass().getClassLoader(), house.getClass().getInterfaces(), dynProxy);
h.bed();
TrafficInteface train = new Train();
DynProxy trainHandler = new DynProxy(train);
TrafficInteface trainProxy = (TrafficInteface) Proxy.newProxyInstance(train.getClass().getClassLoader(), train.getClass().getInterfaces(), trainHandler);
trainProxy.hardBed();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void generatedProxyFiles() throws Exception {
Field field = System.class.getDeclaredField("props");
field.setAccessible(true);
Properties props = (Properties) field.get(null);
props.put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
}
}
運(yùn)行結(jié)果:
脫了鞋
躺在家里的床
--------------
脫了鞋
躺在火車硬臥
--------------
上面的例子我們可以看到動態(tài)代理不僅代理了HouseInterface還代理了TrafficInteface缴淋。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import a.i.HouseInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements HouseInterface {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void bed() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("a.i.HouseInterface").getMethod("bed");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
在生成的代理類中我們可以看到暴露了4個方法,有三個是Object的方法泄朴,有一個是我們定義的方法重抖。所以我們通過invoke可以調(diào)用這些方法。