代理模式是常用的设计模式,一般可分为静态和动态代理。
静态代理
- 继承相同的抽象类
- 实现相同的接口
动态代理
JDK动态代理
实现步骤
- 被代理的类classA以及实现的接口interfaceA
- 创建一个事务处理器,实现接口InvocationHandler,以及invoke方法
- 调用java.lang.reflect.Proxy的静态方法,创建一个代理对象
Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h);
- 通过代理对象调用方法
public class AHandler implements InvocationHandler {
private Object target;
public AHandler(A target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("\n=================");
method.invoke(target);
System.out.println("=================");
Class<? extends Object> proxyClass = proxy.getClass();
System.out.println(" --- proxy class:" + proxyClass.getName());
Class<?> fooProxyClass = proxyClass.getSuperclass();
System.out.println(" --- super proxy class:" + fooProxyClass.getName());
System.out.println(" --- method:" + method.getName());
// 以下是一个死循环
// Method[] methods = proxyClass.getDeclaredMethods();
// for (Method m : methods){
// System.out.println(m.getName());
// if("say".equals(m.getName())){
// System.out.println(" --- 让$Proxy0这个代理对象调用say方法");
// m.invoke(proxy);
// }
// }
return 2;
}
}
public class A implements InterA{
@Override
public void say() {
System.out.println(" --- i love m --- ");
}
@Override
public int hear() {
System.out.println(" --- Saturday --- ");
return 1;
}
public static void main(String[] args) {
A a = new A();
Class<? extends A> aclass = a.getClass();
AHandler handler = new AHandler(a);
Object proxy = Proxy.newProxyInstance(aclass.getClassLoader(), aclass.getInterfaces(), handler);
System.out.println(" --- return proxy class:" + proxy.getClass().getName());
InterA aProxy = (InterA) proxy;
aProxy.say();
int i = aProxy.hear();
System.out.println(i);
int h = aProxy.hashCode();
System.out.println(h);
}
}
//console
--- return proxy class:com.sun.proxy.$Proxy0
=================
--- i love m ---
=================
--- proxy class:com.sun.proxy.$Proxy0
--- super proxy class:java.lang.reflect.Proxy
--- method:say
=================
--- Saturday ---
=================
--- proxy class:com.sun.proxy.$Proxy0
--- super proxy class:java.lang.reflect.Proxy
--- method:hear
2
=================
=================
--- proxy class:com.sun.proxy.$Proxy0
--- super proxy class:java.lang.reflect.Proxy
--- method:hashCode
2
以上是根据视频自己写的测试类,关于JDK动态代理,总结如下:
- 代理对象会代理接口中定义的所有方法,以及从Object继承过来的方法
- 根据JDK规定,代理以$Proxy开头
- 代理类父类是java.lang.reflect.Proxy
- Handler中必须是method.invoke(target),不能是method.invoke(proxy),虽然现在不清楚proxy参数时什么用,但它所代理的方法就是去handler中调用invole方法,即say.invoke(proxy),必然死循环
- 代理方法返回值即invoke的返回值
小结
JDK动态代理的实现原理,基本上就是反射,以say()为例,代理对象调用say(),其实是去调用Handler的invoke方法,其中参数是封装say()的Method对象。
JDK动态代理
- 只能代理实现了接口的类
- 没有实现接口,就不能代理
cglib动态代理
- 针对类来实现代理
- 对指定目标类产生一个子类,通过拦截所以的父类方法完成代理
以下是一个cglib的基本用法
public class BProxy implements MethodInterceptor{
//代理类实例
private Enhancer enhancer = new Enhancer();
//获取代理类
public Object getProxy(Class<?> cls){
//设置父类,即原类
enhancer.setSuperclass(cls);
//回调
enhancer.setCallback(this);
//创建代理类
return enhancer.create();
}
/**
* 拦截所以目标类方法的调用
* @param obj 目标类的实例
* @param m 目标方法的反射对象
* @param arg 目标方法的参数
* @param proxy 代理类的实例
*/
@Override
public Object intercept(Object obj, Method m, Object[] arg, MethodProxy proxy) throws Throwable {
System.out.println("\n=================");
//代理类调用父类的方法,即原方法
proxy.invoke(obj, arg);
System.out.println("=================");
return null;
}
}
注:以上为个人感悟,未读源码验证。