SpringAop中的jdk動態代理技術和cglib動態代理技術

1、Spring Aop中使用到了動態代理技術,對於jdk動態代理,要求必須代理接口,底層是java的反射機制,對於類,使用cglib字節碼增強來動態代理


2、設計模式中簡單的代理模式實現


3、jdk動態代理的實現方法

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//實現了InvocationHandler接口並實現了它的invoke方法
public class ProxyTest implements InvocationHandler{

	//目標代理對象
	private Object target;
	public ProxyTest(){
	}

	//帶參的構造函數,用於傳遞目標代理對象
	public ProxyTest(Object target){
		this.target = target;
	}
	
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("執行方法前");
		//代理對象執行對應的方法 在前面後後面都加上了代碼,這是Aop的一種實現方式,面向切面編程
		method.invoke(target, args);
		System.out.println("執行方法後");
		return target;
	}
	
	public static void main(String[] args) {
		//創建需要被代理的對象
		Sky sky1 = new ProxyTest().new SkyImpl();
		//創建代理對象
		ProxyTest proxyTest = new ProxyTest(sky1);
		//生成代理對象
		Sky sky = (Sky)Proxy.newProxyInstance(SkyImpl.class.getClassLoader(), SkyImpl.class.getInterfaces(),proxyTest );
		//執行方法
		sky.rain();
	}
	
	interface Sky{
		void rain();
	}
	class SkyImpl implements Sky{
		public void rain() {
			System.out.println("天下雨了");
		}
	}
}


4、運行結果



5、反編譯過後,實際上是代理類繼承了Proxy類並且實現了對應代理的接口,由於java只能支持單繼承,所以jdk代理只適用於代理接口,例如 $ProxyClass extends Proxy implements Sky


6、cglib動態代理案例,需要在maven中添加cglib的依賴包

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibTest {

	public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		//設置需要代理的類
		enhancer.setSuperclass(HelloServiceImpl.class);
		//設置回調方法
		enhancer.setCallback(new HelloMethodInterceptor());
		//創建代理對象
		HelloServiceImpl helloServiceImpl = (HelloServiceImpl)enhancer.create();
		//調用代理對象的方法
		helloServiceImpl.sayHello();
	}
	
}

//被代理的類
class HelloServiceImpl{
	
	public void sayHello(){
		System.out.println("Hello,World!");
	}
}

class HelloMethodInterceptor implements MethodInterceptor{
	
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		System.out.println("方法調用前");
		//執行代理對象的方法 在前面後面加通知都可以
		methodProxy.invokeSuper(obj, args);
		System.out.println("方法調用後");
		return obj;
	}
}


7、執行的結果


8、cglib是一種字節碼增強的動態代理技術,它代理的是類,而具體的實現是代理類繼承了需要被代理的類,並增強了它的方法 $ProxyClass extends HelloServiceImpl  注意:cglib不能代理final修飾的類,也不能代理final修飾的方法,因爲不能重寫

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