靜態(tài)代理:
就是一種組合方式的,A類組合目標類,A類A方法中引用目標類的a方法;對其進行輔助實現(xiàn);
若想調(diào)用目標類的a方法,直接可以用A類A方法代理執(zhí)行;
1.動態(tài)代理:
JDK動態(tài)代理:就是字節(jié)碼重組過程,主要是生成新的代理類并實現(xiàn)目標類全部方法;
<font color=Red> 因為是通過實現(xiàn),被代理類都實現(xiàn)接口 </font>
JDK動態(tài)代理過程
1.首先通過getInstance獲取目標類,然后通過反射獲取其全部方法;
2.Proxy.newProxyInstance通過入?yún)ⅲ侯惖腸lassLoader, 類的接口方法,該JDKDemoPorxy;
來創(chuàng)建新的代理對象;并且實現(xiàn)全部接口方法;
Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
- 最終通過invoke 來調(diào)用方法;入?yún)ⅲ盒律傻拇眍悾{(diào)用的目標方法,方法入?yún)?;
作用對原有類的接口方法做業(yè)務增強,比如before(),after()等方法;
public Object invoke(Object proxy, Method method, Object[] args)
4.根據(jù)上述動態(tài)生成java代碼,編譯新生產(chǎn)的.class文件,重新加載到JVM運行
//具體使用例子
//jdk代理類
public class JDKMeipo implements InvocationHandler {
private Object target;
public Object getInstance(Object target) throws Exception {
this.target = target;
Class<?> clazz = target.getClass();
//反射獲取目標類方法,并新生成一個代理類,并實現(xiàn)全部方法,其中invoke可以做邏輯切入
//入?yún)㈩惖腸lassLoader,類的接口,該JDKDemoPorxy
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
//入?yún)ⅲ盒律傻拇眍?,調(diào)用的目標方法,方法入?yún)? @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj = method.invoke(this.target, args);
after();
return obj;
}
private void before() throws Exception {
System.out.println("before+++");
}
private void after() {
System.out.println("after+++");
}
}
public interface Person {
void getName();
Long getCreateTime(String param);
}
//目標類
public class Customer implements Person {
@Override
public void getName() {
System.out.println("sally");
}
@Override
public Long getCreateTime(String param) {
System.out.println(param);
return System.currentTimeMillis();
}
}
//測試使用
public class JDKProxyTest {
public static void main(String[] args) throws Exception {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
Person student = (Person) new JDKMeipo().getInstance(new Customer());
student.getCreateTime();
// Person customer = (Person) new CglibProxyDemo().getInstance(Customer.class);
// customer.getName();
}
}
代理重組字節(jié)碼反編譯后生成的文件:
通過反編譯新的代理類文件$Porxy;可以看到 他實現(xiàn)了所有方法,并在static靜態(tài)塊中用反射找到所有方法以m0,m1,m2....來命名方法
public final class $Proxy0 extends Proxy implements Person {
private static Method m1;
private static Method m3;
private static Method m4;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {省略}
public final void getName() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final Long getCreateTime() throws {
try {
return (Long)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {省略}
public final int hashCode() throws { 省略}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.example.springbootdemo.model.Person").getMethod("getName");
m4 = Class.forName("com.example.springbootdemo.model.Person").getMethod("getCreateTime");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
2.CGlib動態(tài)代理
CGlib動態(tài)代理原理:是通過生成子類繼承目標類,并覆蓋;
CGlib動態(tài)代理過程
1.首先通過Enhancer,設置目標類,并設置代理為回調(diào),生成代理類繼承目標類;
public Object getInstance(Class<?> clazz) throws Exception {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//生成代理類繼承目標類
return enhancer.create();
}
2.當調(diào)用代理類中方法時,通過MethodInterceptor攔截或說回調(diào)到intercept,來觸發(fā)MethodProxy.invokeSuper;
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
before();
//methodProxy invokeSuper觸發(fā)并生FastClass類,通過FastClass機制
Object obj = methodProxy.invokeSuper(o,args);
after();
return obj;
}
若緩存中沒有,其中為目標類和代理類各生成一個FastClass類,這類會為每個方法分配一個index;
FastClassInfo fci = fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);
獲取當前代理類的FastClass類和index,當作入?yún)⒕涂梢灾苯诱{(diào)用方法,省去反射調(diào)用;所以比JDK執(zhí)行效率高;
FastClass不是和代理一起生成的,而是在第一次執(zhí)行MethodProxy.invokeSuper生成的,并放在緩存中;
使用例子
public class CglibProxyDemo implements MethodInterceptor {
public Object getInstance(Class<?> clazz) throws Exception {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//生成代理類繼承目標類
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
before();
//methodProxy invokeSuper觸發(fā)并生FastClass類,通過FastClass機制
Object obj = methodProxy.invokeSuper(o,args);
after();
return obj;
}
private void before() throws Exception {
System.out.println("before+++");
}
private void after() {
System.out.println("after+++");
}
}
public class CglibProxyTest {
public static void main(String[] args) throws Exception {
Person customer = (Person) new CglibProxyDemo().getInstance(Customer.class);
customer.getName();
}
}
代理類調(diào)用方法時,會MethodInterceptor攔截進入intercept,觸發(fā)methodProxy.invokeSuper(o,args);
MethodProxy是很關(guān)鍵的,調(diào)用invokeSuper時,為目標類和代理類各生成一個FastClass類,這類會為每個方法分配一個index;
獲取代理類的FastClass根據(jù)index,調(diào)用方法;
public class MethodProxy {
private Signature sig1;
private Signature sig2;
private CreateInfo createInfo;
private final Object initLock = new Object();
private volatile FastClassInfo fastClassInfo;
···
private void init() {
if (fastClassInfo == null) {
synchronized (initLock) {
if (fastClassInfo == null) {
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
fci.i1 = fci.f1.getIndex(sig1);
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}
。。。
private static class FastClassInfo {
FastClass f1;
FastClass f2;
int i1;
int i2;
}
。。。。
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
//生成FastClass類 ,若有就從緩存中獲取
init();
FastClassInfo fci = fastClassInfo;
//根據(jù)fci.i2的index,去調(diào)用方法
return fci.f2.invoke(fci.i2, obj, args);
}
catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
」