我们都知道代理分为静态代理和动态代理,然而静态代理比较简单,直接将需要被代理的类作为代理类的一
个成员变量即可,但是这种代理在复杂的条件下会变得异常繁琐,且容易出错。这里我们主要说动态代理。
一. javaJDK的动态代理:
这种代理只要给出接口对象和子类的实现,那么就可以实现,其中主要借助于Proxy类的静态方newProxyInstance和InvocationHandler的invoke的方法重写,案例如下:
package com.company;
/**
* Created by Dqd on 2017/4/8.
*/
public interface Animal {
public void shout();
}
public class Dog implements Animal {
@Override
public void shout() {
System.out.println("汪汪..");
}
}
public class JDKProxy implements InvocationHandler {
//被代理对象
private Object animal;
//之所以为动态代理,就是可以接收到不同类型的参数
public Object getInstance(Object animal){
this.animal = animal;
return Proxy.newProxyInstance(animal.getClass().getClassLoader()
,animal.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before shout");
method.invoke(animal,args);
System.out.println("After shout");
return null;
}
}
Test:
public class Main {
public static void main(String[] args){
Animal animal = (Animal) new JDKProxy().getInstance(new Dog());
animal.shout();
}
}
Before shout
汪汪..
After shout
虽然我们实现了动态代理,但是还是不明白为什么使用Proxy.newProxyInstance()就可以生成代理对象的
下面是Proxy类的newProxyInstance的源码:
/**
* loader:类加载器
* constructorParams是InvocationHandler实现类中的变量
* interfaces:目标对象实现的接口
* h:InvocationHandler的实现类
*/
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
/*
* Look up or generate the designated proxy class.
*/
Class cl = getProxyClass(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// 调用代理对象的构造方法(也就是$Proxy0(InvocationHandler h))
Constructor cons = cl.getConstructor(constructorParams);
// 生成代理类的实例并把MyInvocationHandler的实例传给它的构造方法
return (Object) cons.newInstance(new Object[] { h });
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
} catch (IllegalAccessException e) {
throw new InternalError(e.toString());
} catch (InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
throw new InternalError(e.toString());
}
}
PS:通过传入的参数(接口)克隆接口得到interfaces,然后再结合类加载器,得到一个继承Proxy的Class对象(ps:这里的Class对象生成的过程涉及到了缓存的问题,就是这里的getProxyClass方法),通过这个对象得到构造方法对象,构造方法对象再生成实例,这就是代理对象的生成过程。
代理对象的生成明确了,那么实现InvokeHandler的invoke方法由谁来调用呢?
根据参数loader和interfaces调用方法 getProxyClass(loader, interfaces)创建代理类$Proxy0.$Proxy0类 实现了interfaces的接口,并继承了Proxy类;实例化$Proxy0并在构造方法中把继承了InvocationHandler的实例当做参数传过去,接着
$Proxy0调用父类Proxy的构造器,为成员变量赋值;$Proxy0实例强制转换成Animal,并将引用赋给animal。当执行animal.request()方法时,就调用了
$Proxy0类中的request()方法,进而调用父类Proxy中的h的invoke()方法.即InvocationHandler.invoke().
总结:生成代理类的时候,首先调用Proxy.newInstance()方法,并将接口的类加载器,所拥有的接口和InvocationHandler对象传递过去,生成一个继承Proxy的Class对象,然后通过父类的构造器将构造出一个Animal
对象,然后调用request()方法,此方法再去调用invoke()方法。
二.CGlib的动态代理:
package com.company;
/**
* Created by Dqd on 2017/4/8.
*/
public class Animal {
public void Shout(){
System.out.println("汪汪...");
}
}
//在JDK自带的动态代理中实现的是InvocationHandler
public class CGlibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用之前");
methodProxy.invokeSuper(o,objects);
System.out.println("调用之后");
return null;
}
public Object getCGlibProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码动态的创建子类
return enhancer.create();
}
}
public class Main {
public static void main(String[] args){
CGlibProxy cGlibProxy = new CGlibProxy();
Animal animal = (Animal) cGlibProxy.getCGlibProxy(Animal.class);
animal.Shout();
}
}