静态代理
public class SimpleStaticProxyDemo {
// 都实现这个接口
static interface IService {
public void sayHello();
}
// 被代理的类
static class RealService implements IService {
@Override
public void sayHello() {
System.out.println("hello");
}
}
// 代理
static class TraceProxy implements IService {
private IService realService;
public TraceProxy(IService realService) {
this.realService = realService;
}
@Override
public void sayHello() {
System.out.println("entering sayHello");
// 调用实际干活类
this.realService.sayHello();
System.out.println("leaving sayHello");
}
}
public static void main(String[] args) {
IService realService = new RealService();
// 实际干活的类 传入代理类
IService proxyService = new TraceProxy(realService);
// 客户自己使用的是代理类
proxyService.sayHello();
}
}
但是如果要AOP, 很多类需要类似的功能, 如果他们实现的不是IService , 就不能用这个代理类了,
对于日志这种通用的功能, 犯不着每个接口都给它写个代理类
Java SDK动态代理
java.lang.reflect.Proxy类 里面静态方法-
loader
表示类加载器 -
interfaces
表示代理类要实现的接口列表 , 想要返回的代理类是什么类型就往里加接口.class -
h
类型为InvocationHandler,它是一个接口,也定义在java.lang.reflect包中, 就是在里面写对目标类的改造 -
返回值: 返回值类型为Object,可以强制转换为interfaces数组中的一个接口类型
定义h: 同一的附加功能是日志
static class SimpleInvocationHandler implements InvocationHandler {
private Object realObj;
public SimpleInvocationHandler(Object realObj) {
this.realObj = realObj;
}
/**
*
* @param proxy 代理对象本身
* @param method 调用的方法
* @param args 传参
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("entering " + method.getName());
// Object result = method.invoke(proxy, args); 如果改成这样会死循环
Object result = method.invoke(realObj, args);
System.out.println("leaving " + method.getName());
return result;
}
}
使用:
public static void main(String[] args) {
IService realService = new RealService();
ClassLoader classLoader = IService.class.getClassLoader();
Class<?>[] interfaces = {IService.class};
SimpleInvocationHandler h = new SimpleInvocationHandler(realService);
IService proxyService = (IService) Proxy.newProxyInstance(classLoader, interfaces, h);
proxyService.sayHello();
}
其中
IService proxyService = (IService) Proxy.newProxyInstance(classLoader, interfaces, h);
可以替换为:
Class<?> proxyCls = Proxy.getProxyClass(classLoader, interfaces);
Constructor<?> ctor = proxyCls.getConstructor(new Class<?>[]{InvocationHandler.class });
IService proxyService = (IService) ctor.newInstance(h);
Proxy.getProxyClass(类加载器,接口数组)
它会动态生成一个类,类名以$Proxy开头,后跟一个数字
这个动态生成的类 与被代理的对象没有关系,与InvocationHandler h的具体实现也没有关系,只与接口数组有关
public class $Proxy0 extends Proxy
implements SimpleJDKDynamicProxyDemo.IService{//实现了接口IService
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
// 注意这个构造方法 传入h 其他方法都会交给h
public $Proxy0(InvocationHandler h) {
super(h);
}
@Override
public final boolean equals(Object paramObject) {
return ((Boolean) this.h.invoke(this, m1,
new Object[] { paramObject })).booleanValue();
}
@Override
public final void sayHello() {
// 交给h了
this.h.invoke(this, m3, null);
}
@Override
public final String toString() {
return (String) this.h.invoke(this, m2, null);
}
@Override
public final int hashCode() {
return ((Integer) this.h.invoke(this, m0, null)).intValue();
}
static {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("laoma.demo.proxy.SimpleJDKDynamicProxyDemo$IService")
.getMethod("sayHello",new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
}
}
动态代理, 把实现的接口 和 handle 和被代理类 分离, 不同的接口可以用同一个handle,
但是, 必须是有有接口的类 才能被动态代理,返回的代理对象也只能转换到某个接口类型,如果一个类没有接口,或者希望代理非接口中定义的方法,那就没有办法了。
cglib动态代理
基于ASM
第三方的类库cglib(https://github.com/cglib/cglib)可以做到这一点,Spring,Hibernate等都使用该类库。
cglib的实现机制与Java SDK不同,通过继承实现的,也是动态创建了一个类,父类是被代理的类,代理类重写了父类的所有public非final方法,改为调用Callback中的相关方法
被代理的类: 没有接口
class RealService {
public void sayHello() {
System.out.println("hello");
}
}
要加的功能:
class SimpleInterceptor implements MethodInterceptor {
/**
*
* @param object 代理对象
* @param method
* @param args 传参
* @param proxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("entering " + method.getName());
Object result = proxy.invokeSuper(object, args);
System.out.println("leaving " + method.getName());
return result;
}
}
使用:
/**
*
* @param cls 被代理的类
* @param <T> 被代理类的类型
* @return 代理
*/
@SuppressWarnings("unchecked")
private static <T> T getProxy(Class<T> cls) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(cls);//设置被代理的类
// 设置处理类
enhancer.setCallback(new SimpleInterceptor());
return (T) enhancer.create();
}
public static void main(String[] args) {
// 直接对类代理 不用创建原类的实例
RealService proxyService = getProxy(RealService.class);
proxyService.sayHello();
}
Java SDK代理的是对象,需要先有一个实际对象,
cglib代理的是类,创建的对象只有一个。
网友评论