1、jdk代理
- 代理类没有源码,在运行期间直接生成字节码,通过传入的类加载器加载
- 为了实现功能的增强,添加前置通知、后置通知,环绕通知等
- 代理类和目标对象是兄弟关系,都是实现了某个接口
- 目标类可以被final修饰,不可被继承,不影响兄弟对象(代理类)创建
public class JdkProxyDemo {
public static void main(String[] param) throws IOException {
Target target = new Target();
ClassLoader loader = JdkProxyDemo.class.getClassLoader();
Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, (p, method, args) -> {
System.out.println("before...");
Object result = method.invoke(target, args);
System.out.println("after....");
return result;
});
System.out.println("代理类类型:"+proxy.getClass());
System.out.println("---------------通过代理类调用目标方法-----------");
proxy.foo();
}
}
interface Foo {
void foo();
}
class Target implements Foo {
public void foo() {
System.out.println("target foo");
}
}
输出结果:
代理类类型:class com.xc.a11.$Proxy0
---------------通过代理类调用目标方法-----------
before...
target foo
after....
Process finished with exit code 0
2、cglib代理
- 代理是子类型, 目标是父类型,所以目标类和方法都不能为final
- methodProxy 可以避免使用反射调用,spring默认使用
- 与jdk代理一样也是没有class文件,运行期间直接生成字节码文件
public class CglibProxyDemo {
public static void main(String[] param) {
Target proxy = (Target) Enhancer.create(Target.class, (MethodInterceptor)
(p, method, args, methodProxy) -> {
System.out.println("before...");
Object result = methodProxy.invokeSuper(p, args);
System.out.println("after...");
return result;
});
proxy.foo();
}
}
class Target {
public void foo() {
System.out.println("target foo");
}
}
输出结果:
before...
target foo
after...
Process finished with exit code 0
3、手写jdk代理
interface Foo {
void foo();
int bar();
}
class Target implements Foo {
public void foo() {
System.out.println("target foo");
}
@Override
public int bar() {
System.out.println("target bar");
return 100;
}
}
- 代理类实现功能增强的方法的接口
- 参数分别为:代理类本身,代理类执行的方法,方法参数
interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
public class $Proxy0 implements Foo {
private final InvocationHandler invocationHandler;
public $Proxy0(InvocationHandler h) {
this.invocationHandler = h;
}
private static final Method foo;
private static final Method bar;
static {
try {
foo = Foo.class.getMethod("foo");
bar = Foo.class.getMethod("bar");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
@Override
public void foo() {
try {
invocationHandler.invoke(this, foo, new Object[0]);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public int bar() {
try {
Object result = invocationHandler.invoke(this, bar, new Object[0]);
return (int) result;
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
- 创建代理类传入InvocationHandler的匿名内部类
- 通过目标对象Target反射调用对应方法,前后可以添加功能增强
public static void main(String[] param) {
Foo proxy = new $Proxy0(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
System.out.println("before...");
Object invoke = method.invoke(new Target(), args);
System.out.println("after...");
return invoke;
}
});
proxy.foo();
proxy.bar();
}
输出结果:
before...
target foo
after...
before...
target bar
after...
Process finished with exit code 0
JDK动态代理实现与上方不同的是:没有class文件,在程序运行期间的内存中生成以上的字节码文件,所以叫动态代理
4、手写cglib代理
4.1、反射之目标调用
public class Target {
public void save() {
System.out.println("save()");
}
public void save(int i) {
System.out.println("save(int)");
}
public void save(long j) {
System.out.println("save(long)");
}
}
- 代理类,继承目标类,目标类的子类
- 创建代理类需要MethodInterceptor接口实现类(环绕增强方法及中间的调用目标方法)
- 代理类调用方法即是调用MethodInterceptor实现类的内容
public class Proxy extends Target {
private MethodInterceptor methodInterceptor;
public Proxy(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
}
private final static Method save0;
private final static Method save1;
private final static Method save2;
private final static MethodProxy save0Proxy;
private final static MethodProxy save1Proxy;
private final static MethodProxy save2Proxy;
static {
try {
save0 = Target.class.getMethod("save");
save1 = Target.class.getMethod("save", int.class);
save2 = Target.class.getMethod("save", long.class);
save0Proxy = MethodProxy.create(Target.class, Proxy.class, "()V", "save", "saveSuper");
save1Proxy = MethodProxy.create(Target.class, Proxy.class, "(I)V", "save", "saveSuper");
save2Proxy = MethodProxy.create(Target.class, Proxy.class, "(J)V", "save", "saveSuper");
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
public void saveSuper() {
super.save();
}
public void saveSuper(int i) {
super.save(i);
}
public void saveSuper(long j) {
super.save(j);
}
@Override
public void save() {
try {
methodInterceptor.intercept(this, save0, new Object[0], save0Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(int i) {
try {
methodInterceptor.intercept(this, save1, new Object[]{i}, save1Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public void save(long j) {
try {
methodInterceptor.intercept(this, save2, new Object[]{j}, save2Proxy);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
}
public interface MethodInterceptor extends Callback {
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
- method.invoke(target, args): 通过目标类获取到method,再利用method,target,args反射调用方法
- methodProxy.invoke(target, args): 通过目标类直接调用方法,无反射
- methodProxy.invokeSuper(p, args): 通过代理类调用方法,无反射
- MethodProxy.create:创建methodProxy,内部调用saveSuper(带原始功能的方法)
public class A13 {
public static void main(String[] args) {
Target target = new Target();
Proxy proxy = new Proxy(new MethodInterceptor() {
@Override
public Object intercept(Object p, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
return method.invoke(target, args);
}
});
proxy.save();
proxy.save(1);
proxy.save(2L);
}
}
输出结果:
before...
save()
before...
save(int)
before...
save(long)
Process finished with exit code 0
4.2、无反射之目标调用
methodProxy.invoke(target, args):methodProxy对象的创建及invoke的执行原理
- Signature:签名(描述方法名字-save及方法入参-()和方法返回值-V)
- 每个方法指定一个唯一的编号通过getIndex方法与签名一一对应
- 在invoke中通过编号使用目标类调用不同的方法
public class TargetFastClass {
private final static Signature s0 = new Signature("save", "()V");
private final static Signature s1 = new Signature("save", "(I)V");
private final static Signature s2 = new Signature("save", "(J)V");
public int getIndex(Signature signature) {
if (s0.equals(signature)) {
return 0;
} else if (s1.equals(signature)) {
return 1;
} else if (s2.equals(signature)) {
return 2;
}
return -1;
}
public Object invoke(int index, Object target, Object[] args) {
if (index == 0) {
((Target) target).save();
return null;
} else if (index == 1) {
((Target) target).save((int) args[0]);
return null;
} else if (index == 2) {
((Target) target).save((long) args[0]);
return null;
} else {
throw new RuntimeException("无此方法");
}
}
public static void main(String[] args) {
TargetFastClass fastClass = new TargetFastClass();
int index = fastClass.getIndex(new Signature("save", "(I)V"));
System.out.println(index);
fastClass.invoke(index, new Target(), new Object[]{100});
}
}
输出结果:这里的方法是目标类直接调用的save(int i)方法
1
save(int)
Process finished with exit code 0
4.3、无反射之代理调用
methodProxy.invokeSuper(p, args):methodProxy对象的创建及invokeSuper的执行原理
- 签名和方法标号与无反射目标调用一样
- invoke则是通过代理类调用saveSuper方法的super.save(),实际还是目标类的方法实现
public class ProxyFastClass {
static Signature s0 = new Signature("saveSuper", "()V");
static Signature s1 = new Signature("saveSuper", "(I)V");
static Signature s2 = new Signature("saveSuper", "(J)V");
public int getIndex(Signature signature) {
if (s0.equals(signature)) {
return 0;
} else if (s1.equals(signature)) {
return 1;
} else if (s2.equals(signature)) {
return 2;
}
return -1;
}
public Object invoke(int index, Object proxy, Object[] args) {
if (index == 0) {
((Proxy) proxy).saveSuper();
return null;
} else if (index == 1) {
((Proxy) proxy).saveSuper((int) args[0]);
return null;
} else if (index == 2) {
((Proxy) proxy).saveSuper((long) args[0]);
return null;
} else {
throw new RuntimeException("无此方法");
}
}
public static void main(String[] args) {
ProxyFastClass fastClass = new ProxyFastClass();
int index = fastClass.getIndex(new Signature("saveSuper", "()V"));
System.out.println(index);
fastClass.invoke(index, new Proxy(null), new Object[0]);
}
}
输出结果: 这里只需要代理类里面的saveSuper方法,MethodInterceptor这里没有用到
0
save()
Process finished with exit code 0
|