Java中的代理
2020-04-12 本文已影响0人
被虐的小鸡
如有转载请注明出处https://www.jianshu.com/p/bc478bc46515
绪论
java中的代理分为静态代理和动态代理,静态代理使用于同一类型的群体的代理,而动态代理适用于不同群体之间的代理,静态代理在编译器就已经存在了,并且编译成class文件,在我看来代理可以用来增强功能。
静态代理
举个例子说明,一看就知道什么是静态代理了
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();
}
}
运行结果:
把饭盛碗里
坐在凳子上
吃西虹市炒鸡蛋
洗碗
---------------------
把饭盛碗里
坐在凳子上
吃辅食
洗碗
上面的例子可以看出这个代理类只能代理Person群体,如果想代理佳通工具或者水果等需要在定义自己的代理类。
动态代理
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");
}
}
运行结果:
脱了鞋
躺在家里的床
--------------
脱了鞋
躺在火车硬卧
--------------
上面的例子我们可以看到动态代理不仅代理了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可以调用这些方法。