關於Java代理那些事兒

代理是啥?就是代替你執行你持有的主要功能,並且能在你的基礎之上完成一些其他的功能。代理的目的就是生成一個和原對象具有同樣功能的對象。在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進行代理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章