您的位置:首页 > 编程语言 > Java开发

Java动态代理全面分析

2016-09-29 16:27 267 查看

代理模式

解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用;

代理模式需要以下几个角色:

1 主题:规定代理类和真实对象共同对外暴露的接口;

2 代理类:专门代理真实对象的类;

3 真实对象:需要被代理的对象;

代理解决的主要的业务就是需要在 真实对象的某个接口 前后处理一些事情,框架中多会用到这种功能,比如 打日志、记录时间等

静态代理

静态代理是指自己动手编写代码实现代理类;

优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。

缺点:每一个真实对象都需要一个具体的代理类,不能做到可重用;

静态代理比较简单,下边用代码来具体说明;

主题接口:IAnimal

public interface IAnimal {
/**
* 动物叫
*/
void bark();
}


真实对象:Dog

代理:DogProxy

public class DogProxy implements IAnimal {
private Dog dog;

public DogProxy(Dog dog) {
this.dog = dog;
}

@Override
public void bark() {
long l = System.currentTimeMillis();
System.out.println("dog will bark...");
this.dog.bark();
System.out.println("dog has barked which takes " + (System.currentTimeMillis() - l) + " ms !");
}
}


静态代理使用:

public class StaticProxyTest {

public static void main(String[] args) {

IAnimal dog = new Dog("大黄");

IAnimal dogProxy = new DogProxy(dog);

dogProxy.bark();
}
}


代理和真实对象对外暴露一致

动态代理

动态代理是指在运行时动态生成代理类;

jdk

要使用Java中原生的动态代理,需要用到以下几个类和接口

接口InvocationHandler

Proxy类

我们还是用静态代理用到的代码:主题接口IAnimal和真实对象Dog不变,去掉DogProxy和StaticProxyTest,增加以下代码

DogProxyInvocationHandler

public class DogProxyInvocationHandler implements InvocationHandler {
private Object animal;

public DogProxyInvocationHandler(Object animal) {
this.animal = animal;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy class:" + proxy.getClass() + ",class:" + getClass() + ",method:" + method);
Object obj = method.invoke(animal, args);
System.out.println("obj:" + obj);
return obj;
}
}


DynamicProxyTest

public class DynamicProxyTest {

public static void main(String[] args) {

IAnimal dog = new Dog("大黄");

InvocationHandler invocationHandler = new DogProxyInvocationHandler(dog);
IAnimal animal = (IAnimal) Proxy.newProxyInstance(dog.getClass().getClassLoader(),
dog.getClass().getInterfaces(),
invocationHandler);
animal.bark();
}

}


可以看出:Java动态代理 我们必须有真实对象,实现了InvocationHandler接口的自己的处理类,然后通过Proxy生成代理类

输出如下:

proxy class:class com.sun.proxy.$Proxy0,class:class com.shock.base.proxy.dynamic.DogProxyInvocationHandler,method:public abstract void com.shock.base.proxy.dynamic.IAnimal.bark()

大黄 bark:wang wang wang ...
obj:null

这里动态代理的优势相比静态代理为:即使真实对象有N个接口,我们的invocationHandler只需要一个Invoke方法即可!

这里有几个问题:

1 动态代理生成的class name为什么是 $Proxy0 ?

[b]

public class Animal$$EnhancerByCGLIB$$223151cf extends com.shock.base.proxy.cglib.Animal implements net.sf.cglib.proxy.Factory {
private boolean CGLIB$BOUND;
public static java.lang.Object CGLIB$FACTORY_DATA;
private static final java.lang.ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final net.sf.cglib.proxy.Callback[] CGLIB$STATIC_CALLBACKS;
private net.sf.cglib.proxy.MethodInterceptor CGLIB$CALLBACK_0;
private net.sf.cglib.proxy.NoOp CGLIB$CALLBACK_1;
private static java.lang.Object CGLIB$CALLBACK_FILTER;
private static final java.lang.reflect.Method CGLIB$bark$0$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$bark$0$Proxy;
private static final java.lang.Object[] CGLIB$emptyArgs;
private static final java.lang.reflect.Method CGLIB$singSong$1$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$singSong$1$Proxy;
private static final java.lang.reflect.Method CGLIB$equals$3$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$equals$3$Proxy;
private static final java.lang.reflect.Method CGLIB$toString$4$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$toString$4$Proxy;
private static final java.lang.reflect.Method CGLIB$hashCode$5$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$hashCode$5$Proxy;

static void CGLIB$STATICHOOK1() { /* compiled code */ }

final void CGLIB$bark$0() { /* compiled code */ }

public final void bark() { /* compiled code */ }

final void CGLIB$singSong$1(java.lang.String s) { /* compiled code */ }

public final void singSong(java.lang.String s) { /* compiled code */ }

final boolean CGLIB$equals$3(java.lang.Object o) { /* compiled code */ }

public final boolean equals(java.lang.Object o) { /* compiled code */ }

final java.lang.String CGLIB$toString$4() { /* compiled code */ }

public final java.lang.String toString() { /* compiled code */ }

final int CGLIB$hashCode$5() { /* compiled code */ }

public final int hashCode() { /* compiled code */ }

public static net.sf.cglib.proxy.MethodProxy CGLIB$findMethodProxy(net.sf.cglib.core.Signature signature) { /* compiled code */ }

public Animal$$EnhancerByCGLIB$$223151cf() { /* compiled code */ }

public static void CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

public static void CGLIB$SET_STATIC_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

private static final void CGLIB$BIND_CALLBACKS(java.lang.Object o) { /* compiled code */ }

public java.lang.Object newInstance(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

public java.lang.Object newInstance(net.sf.cglib.proxy.Callback callback) { /* compiled code */ }

public java.lang.Object newInstance(java.lang.Class[] classes, java.lang.Object[] objects, net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }

public net.sf.cglib.proxy.Callback getCallback(int i) { /* compiled code */ }

public void setCallback(int i, net.sf.cglib.proxy.Callback callback) { /* compiled code */ }

public net.sf.cglib.proxy.Callback[] getCallbacks() { /* compiled code */ }

public void setCallbacks(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
}


View Code
该段代码最后实在没办法生成,是将CGLib代码源码下载,然后插入片段代码生成的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: