JDK Proxy
public interface Rent {
void rent();
}
public class Target implements Rent{
@Override
public void rent() {
System.out.println("target rent");
}
}
public class $Proxy0 implements Rent {
@Override
public void rent() {
// 1.功能增强
System.out.println("before");
// 2.调用目标
new Target().rent();
}
}
public static void main(String[] args) {
$Proxy0 proxy0 = new $Proxy0();
proxy0.rent();
}
由于功能增强是不确定的,所以抽象出来

在触发(invoke)真实角色的方法之前或者之后做一些额外的业务。那么,为了构造出具有通用性和简单性的代理类,可以将所有的触发真实角色动作交给一个触发的管理器,让这个管理器统一地管理触发。这种管理器就是Invocation Handler
public interface InvocationHandler {
void invoke();
}
public class $Proxy0 implements Rent {
private InvocationHandler h;
public $Proxy0(InvocationHandler h) {
this.h = h;
}
@Override
public void rent() {
h.invoke();
}
}
public static void main(String[] args) {
$Proxy0 proxy0 = new $Proxy0(() -> {
System.out.println("before proxy0");
new Target().rent();
});
proxy0.rent();
}
问题:调用目标是写死的,如果被代理类中有多个方法
public interface Rent {
void rent() throws NoSuchMethodException;
void host();
}
public class Target implements Rent{
@Override
public void rent() {
System.out.println("target rent");
}
@Override
public void host() {
System.out.println("target host");
}
}
public interface InvocationHandler {
void invoke(Method method, Object[] args) throws InvocationTargetException, IllegalAccessException;
}
public class $Proxy0 implements Rent {
private InvocationHandler h;
public $Proxy0(InvocationHandler h) {
this.h = h;
}
@Override
public void rent() {
Method rent = null;
try {
rent = Rent.class.getMethod("rent");
h.invoke(rent, new Object[0]);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void host() {
Method host = null;
try {
host = Rent.class.getMethod("host");
h.invoke(host, new Object[0]);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
$Proxy0 proxy0 = new $Proxy0((method, params) -> {
System.out.println("before proxy0");
method.invoke(new Target(), params);
});
proxy0.rent();
proxy0.host();
}
代理和目标需要实现同一个接口,为了让代理内的代码不固定死,需要设计一个接口 InvocationHandler 来回调代理内的抽象操作 invoke
动态代理工作的基本模式就是将自己的方法功能的实现交给 InvocationHandler角色,外界对Proxy角色中的每一个方法的调用,Proxy角色都会交给InvocationHandler来处理,而InvocationHandler则调用具体对象角色的方法。
问题:返回值处理
public interface Rent {
void rent() throws NoSuchMethodException;
int host();
}
public class Target implements Rent{
@Override
public void rent() {
System.out.println("target rent");
}
@Override
public int host() {
System.out.println("target host");
return 100;
}
}
public interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException;
}
public class $Proxy0 implements Rent {
private InvocationHandler h;
public $Proxy0(InvocationHandler h) {
this.h = h;
}
static Method rent;
static Method host;
static {
try {
rent = Rent.class.getMethod("rent");
host = Rent.class.getMethod("host");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
@Override
public void rent() {
try {
h.invoke(this, rent, new Object[0]);
} catch (RuntimeException | Error e) {
throw new RuntimeException(e);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public int host() {
try {
return (int) h.invoke(this, host, new Object[0]);
} catch (RuntimeException | Error e) {
throw new RuntimeException(e);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
public static void main(String[] args) {
$Proxy0 proxy0 = new $Proxy0((proxy, method, params) -> {
System.out.println("before proxy0");
return method.invoke(new Target(), params);
});
proxy0.rent();
int host = proxy0.host();
System.out.println(host);
}
向 JDK 靠拢,继承 Proxy 类

public class $Proxy0 extends Proxy implements Rent {
static Method rent;
static Method host;
static {
try {
rent = Rent.class.getMethod("rent");
host = Rent.class.getMethod("host");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
protected $Proxy0(InvocationHandler h) {
super(h);
}
@Override
public void rent() {
try {
h.invoke(this, rent, new Object[0]);
} catch (RuntimeException | Error e) {
throw new RuntimeException(e);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public int host() {
try {
return (int) h.invoke(this, host, new Object[0]);
} catch (RuntimeException | Error e) {
throw new RuntimeException(e);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
Cglib Proxy
public class Target {
public void save1(){
System.out.println("save1");
}
public void save2(int i){
System.out.println("save2" + i);
}
}
public class Proxy extends Target{
private MethodInterceptor methodInterceptor;
public Proxy(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
static Method save1;
static Method save2;
static {
try {
save1 = Target.class.getMethod("save1");
save2 = Target.class.getMethod("save2", int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
@Override
public void save1() {
try {
methodInterceptor.intercept(this, save1,new Object[0], null);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public void save2(int i) {
try {
methodInterceptor.intercept(this, save2,new Object[]{i}, null);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
Target target = new Target();
Proxy proxy = new Proxy(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before");
return method.invoke(target, objects);
}
});
proxy.save1();
proxy.save2(10);
}

被折叠的 条评论
为什么被折叠?



