代理是啥?就是代替你執行你持有的主要功能,並且能在你的基礎之上完成一些其他的功能。代理的目的就是生成一個和原對象具有同樣功能的對象。在Java中,代理是一種設計模式。在Spring的面向切面編程(AOP)中,主要就是利用動態代理來實現代碼的織入。
代理分爲動態代理和靜態代理。顧名思義,動態代理比靜態代理擴展性更高,動態代理不用爲每一個實現類維護一個代理類。
靜態代理
爲不同的被代理類都維護一個代理類,維護工作量大,不利於擴展。
建立接口類,即被代理類。
Worker.java 工人接口類
public interface Worker {
public void working();
public void resting();
}
SimpleWorker.java 工人實現類
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;
// 構造函數傳入需要執行的類
public WorkerProxy(Worker worker) {
this.worker = worker;
}
// 代理方法,調用具體實現方法
public void working() {
System.out.println("excute static proxy.");
worker.working();
}
}
運行結果:
excute static proxy.
I'm working!
動態代理
動態代理分爲JDK動態代理與CGLIB動態代理。
JDK動態代理
JDK動態代理是jre庫提供的一種方法,無需額外引入。它是通過類的接口生成代理類。
生成一個jdk代理,需要實現InvocationHandler接口,重寫invoke方法。再用Proxy.newProxyInstance去生成代理類。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* jdk 動態代理
* @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 動態代理
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動態代理
CGLIB是通過繼承父類的公有方法,然後進行重寫來實現的。在代碼中代理類需要實現MethodInterceptor接口,重寫intercept方法。配合Enhancer生成動態代理類。
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.");
// 執行父類方法
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 動態代理
CglibProxy cglibProxy = new CglibProxy();
Object instance = cglibProxy.getInstance(SimpleWorker.class);
Worker obj2 = (Worker) instance;
obj2.working();
}
}
運行結果:
excute cglib proxy.
I'm working!
Spring 默認使用jdk動態代理,而當類沒有接口類時,使用CGLIB進行代理。