静态代理
public interface IBank {
/**
* 办理银行卡
*/
void applyBank();
}
/**
* 被代理类
*/
public class Man implements IBank{
@Override
public void applyBank() {
System.out.println("自己做一些事情");
}
}
/**
* 代理类
*/
public class Saleman implements IBank{
private IBank bank; //持有一个具体被代理者的引用
public Saleman(IBank bank) {
this.bank = bank;
}
@Override
public void applyBank() {
System.out.println("代理执行前做一些事情");
bank.applyBank();
System.out.println("代理执行后做做一些事情");
}
}
public static void main(String[] args) {
IBank man = new Man();
IBank saleman = new Saleman(man);
saleman.applyBank();
}
静态代理如上示例所示,代理者的代码右程序员自己或通过一些自动化工具生成固定的代码再对其进行编译,也就是说在我们的代码运行前代理类的class编译文件就已经存在了。而动态代理则与静态代理相反,通过反射机制动态的生成代理者的对象,也就是说我们在code阶段压根就不需要知道代理谁,代码谁会在执行阶段决定。Java给我们提供了一个便捷的动态代理接口InvocationHandler,实现该接口需要重写其调用方法invoke
动态代理
实现方式1(基于 JDK 动态代理)
public static void main(String[] args) {
IBank bank = new Man();
IBank proxy = (IBank) Proxy.newProxyInstance(IBank.class.getClassLoader(),
//new Class[]{IBank.class},//或者//可以代理多个
bank.getClass().getInterfaces(),
new BankProxy(bank));
proxy.applyBank();
}
public static class BankProxy implements InvocationHandler{
private Object obj;//被代理类的引用
public BankProxy(Object obj) {
this.obj = obj;
}
/**
* 执行被代理类的具体方法
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前");
Object invoke = method.invoke(obj, args);
System.out.println("执行后");
return invoke;
}
}
实现方式2(基于 JDK 动态代理)
/**
* 此方式相当于Proxy.newProxyInstance的内部实现
*/
public class TestDynamic2 {
public static void main(String[] args) throws Exception {
IBank bank = new Man();
//创建代理类,是一个字节码文件
Class<?> proxyClass = Proxy.getProxyClass(IBank.class.getClassLoader(), bank.getClass().getInterfaces());
//通过 proxyClass 获得 一个带有InvocationHandler参数的构造器constructor
Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
constructor.setAccessible(true);
//通过构造器创建一个 动态代理类 实例
IBank proxy = (IBank) constructor.newInstance(new BankProxy(bank));
proxy.applyBank();
}
public static class BankProxy implements InvocationHandler {
private Object obj;//被代理类的引用
public BankProxy(Object obj) {
this.obj = obj;
}
/**
* 执行被代理类的具体方法
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前...");
Object invoke = method.invoke(obj, args);
System.out.println("执行后...");
return invoke;
}
}
}
原理分析
1.jdk动态代理是由java内部的反射机制来实例化代理对象,并代理的调用委托类方法
2.会生成全新的Class
3.JDK通过byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);生成代理类的
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
//创建代理类
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
final Class<?>[] intfs = interfaces.clone();
//创建代理类
Class<?> cl = getProxyClass0(loader, intfs);
try {
//通过 proxyClass 获得 一个带有InvocationHandler参数的构造器constructor
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//通过构造器创建一个 动态代理类 实例
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
}
//...
}
}
//getProxyClass0最终会执行ProxyClassFactory的apply方法
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
//代理类名前缀
private static final String proxyClassNamePrefix = "$Proxy";
//代理类个数记录,拼接在$Proxy后面,如$Proxy0
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
//...
if (proxyPkg == null) {
//如果代理的接口都是public的,包名为com.sun.proxy.
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;//com.sun.proxy.$Proxy0
//生成代理类,只加载到内存中,不保存到本地
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
//加载类,加载字节码为Class
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
}
}
}
将生成的代理类保存到本地,查看$Proxy0的实现
//生成IBank的代理类,保存到本地文件
public static void main(String[] args) throws Exception{
byte[] proxyAnimals = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{IBank.class});
OutputStream os = new FileOutputStream("$Proxy0.class");
os.write(proxyAnimals);
os.flush();
os.close();
}
//动态生成的IBank的代理类
import com.cj.learn.proxy.statics.IBank;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements IBank {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void applyBank() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.cj.learn.proxy.statics.IBank").getMethod("applyBank");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
通过查看代理类$Proxy0类的实现public final class $Proxy0 extends Proxy implements IBank,可以发现其继承了Proxy,因为Java单继承,所以Java动态代理只能代理接口的实现类,通过查看applyBank()的实现super.h.invoke(this, m3, (Object[])null);,调用了父类的h,而h即是InvocationHandler(实现类中维护着被代理对象,在invoke时调用),每个方法都是通过反射调用InvocationHandler的invoke方法,而在invoke方法中调用被代理对象(target:bank)的方法,所以invoke方法中调用的 method.invoke(obj, args)中的obj是被代理对象,而不能传参数中的proxy,proxy是代理类,并不是被代理类,因为代理类和被代理类都继承了IBank接口,所以方法签名是一致的。其实静态代理和动态代理的代码原理其实差不多,只是静态代理的代码是在编译前书写的,而动态代理是在运行期间,动态生成的代码而已。
动态代理通过一个代理类来代理N多个被代理类,其实质是对代理者与被代理者进行解耦,使两者直接没有 直接的耦合关系。相对而言静态代理则只能为给定接口下的实现类做代理,如果接口不同那么就需要重新定义不同代理类,较为复杂,但是静态代理更符合面向对象原则。
实现方式3(基于CGlib 动态代理)
/**
* cglib 实现动态代理
*/
public class TestDynamic4 {
public static void main(String[] args) {
//创建增强类
Enhancer enhancer = new Enhancer();
//设置超类,因为cglib基于父类 生成代理子类
enhancer.setSuperclass(Man.class);
//设置回调,也就是我们的拦截处理
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("执行前...");
Object result=methodProxy.invokeSuper(o, objects);
System.out.println("执行后...");
return result;
}
});
//创建代理类
Man man = (Man) enhancer.create();
//执行方法
man.applyBank();
}
}
1.基于继承被代理类生成代理子类,不用实现接口。只需要被代理类是非final 类即可。
2.cglib动态代理底层是借助asm字节码增强技术
3.会生成全新的Class
cglib特点总结
1.CGlib可以传入接口也可以传入普通的类,接口使用实现的方式,普通类使用会使用继承的方式生成代理类.
2.由于是继承方式,如果是 static方法,private方法,final方法等描述的方法是不能被代理的
3.做了方法访问优化,使用建立方法索引的方式避免了传统JDK动态代理需要通过Method方法反射调用.
4.提供callback 和filter设计,可以灵活地给不同的方法绑定不同的callback。编码更方便灵活。
5.CGLIB会默认代理Object中equals,toString,hashCode,clone等方法。比JDK代理多了clone。
静态代理和动态代理是从code方面来区分代理模式的两种方式。
静态代理运用:RxJava
动态代理运用:插件化,Spring AOP