代理是啥?就是代替你執(zhí)行你持有的主要功能滴肿,并且能在你的基礎之上完成一些其他的功能岳悟。代理的目的就是生成一個和原對象具有同樣功能的對象。在Java中泼差,代理是一種設計模式贵少。在Spring的面向切面編程(AOP)中,主要就是利用動態(tài)代理來實現(xiàn)代碼的織入堆缘。
代理分為動態(tài)代理和靜態(tài)代理滔灶。顧名思義,動態(tài)代理比靜態(tài)代理擴展性更高套啤,動態(tài)代理不用為每一個實現(xiàn)類維護一個代理類宽气。
靜態(tài)代理
為不同的被代理類都維護一個代理類随常,維護工作量大,不利于擴展萄涯。
建立接口類绪氛,即被代理類。
Worker.java 工人接口類
public interface Worker {
public void working();
public void resting();
}
SimpleWorker.java 工人實現(xiàn)類
public class SimpleWorker implements Worker {
@Override
public void working() {
System.out.println("I'm working!");
}
@Override
public void resting() {
System.out.println("I'm resting!");
}
}
需求涝影,通過代理調用SimpleWorker的具體的方法枣察,且處理其他邏輯(輸出一句話):
public class WorkerProxy {
private Worker worker;
// 構造函數(shù)傳入需要執(zhí)行的類
public WorkerProxy(Worker worker) {
this.worker = worker;
}
// 代理方法,調用具體實現(xiàn)方法
public void working() {
System.out.println("excute static proxy.");
worker.working();
}
}
運行結果:
excute static proxy.
I'm working!
動態(tài)代理
動態(tài)代理分為JDK動態(tài)代理與CGLIB動態(tài)代理燃逻。
JDK動態(tài)代理
JDK動態(tài)代理是jre庫提供的一種方法序目,無需額外引入。它是通過類的接口生成代理類伯襟。
生成一個jdk代理猿涨,需要實現(xiàn)InvocationHandler接口,重寫invoke方法姆怪。再用Proxy.newProxyInstance去生成代理類叛赚。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* jdk 動態(tài)代理
* @author guilin
*
*/
public class JdkProxy implements InvocationHandler{
private Object target;
public JdkProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("excute jdk proxy.");
Object result = method.invoke(target, args);
return result;
}
public Object getInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
測試類:
public class Test {
public static void main(String[] args) {
// JDK 動態(tài)代理
SimpleWorker simpleWorker = new SimpleWorker();
JdkProxy dynamicProxy = new JdkProxy(simpleWorker);
Object proxyObj = dynamicProxy.getInstance();
Worker obj = (Worker) proxyObj;
obj.working();
}
}
運行結果:
excute jdk proxy.
I'm working!
CGLIB動態(tài)代理
CGLIB是通過繼承父類的公有方法,然后進行重寫來實現(xiàn)的稽揭。在代碼中代理類需要實現(xiàn)MethodInterceptor接口俺附,重寫intercept方法。配合Enhancer生成動態(tài)代理類溪掀。
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
@Override
public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable {
System.out.println("excute cglib proxy.");
// 執(zhí)行父類方法
Object result = methodproxy.invokeSuper(obj, aobj);
return result;
}
public Object getInstance(Class<?> superClass) {
// 獲取代理實例
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(superClass);
enhancer.setCallback(this);
return enhancer.create();
}
}
測試類:
public class Test {
public static void main(String[] args) {
// CGLIB 動態(tài)代理
CglibProxy cglibProxy = new CglibProxy();
Object instance = cglibProxy.getInstance(SimpleWorker.class);
Worker obj2 = (Worker) instance;
obj2.working();
}
}
運行結果:
excute cglib proxy.
I'm working!
Spring 默認使用jdk動態(tài)代理事镣,而當類沒有接口類時,使用CGLIB進行代理揪胃。