1. 程式人生 > >spring 動態代理

spring 動態代理

利用JDK的反射機制(proxyJDK)

而spring預設使用的就是AspectJ來實現的動態代理,spring自己的AOP就是使用AspectJ來實現的!

package cn.xhx.jdkproxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 此攔截器為PersonDao加強功能(新增事務)
 * @author LenovoY510P
 *
 */
public class MyInterceptor implements InvocationHandler{
	private Object target;
	private Transaction transaction;
	
	public MyInterceptor(Object target, Transaction transaction) {
		super();
		this.target = target;
		this.transaction = transaction;
	}
 
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		/**
		 * 1、開啟事物
		 * 2、判斷方法名,執行方法
		 */
		String methodName = method.getName();
		if(methodName.equals("savePerson") || 
				methodName.equals("deletePerson") || 
				methodName.equals("updatePerson")) {
			transaction.beginTransaction();
			method.invoke(target);
			transaction.commit();
		} else {
			System.out.println("balabala...");
		}
		return null;
	}
	
}

package cn.xhx.jdkproxy;
 
public class Transaction {
	public void beginTransaction() {
		System.out.println("begin transaction");
	}
	public void commit() {
		System.out.println("commit");
	}
}

package cn.xhx.jdkproxy;
 
public class PersonDaoImpl implements PersonDao {
 
	public void savePerson() {
		// TODO Auto-generated method stub
		System.out.println("sava person()");
	}
	
}

package cn.xhx.jdkproxy;
 
import java.lang.reflect.Proxy;
 
import org.junit.Test;
 
public class ProxyJDKTest {
	@Test
	public void testJDKProxy() {
		Object target = new PersonDaoImpl();
		Transaction transaction = new Transaction();
		/**
		 * 代理的三大引數
		 * 	1、目標類的classLoader
		 * 	2、目標類的實現的所有介面的.class
		 * 	3、攔截器
		 */
		MyInterceptor myInterceptor = new MyInterceptor(target, transaction);
		PersonDao personDao = (PersonDao)Proxy.newProxyInstance(target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), myInterceptor);
		personDao.savePerson();
		
	}
}

總結 一個典型的動態代理建立物件過程可分為以下四個步驟: 1、通過實現InvocationHandler介面建立自己的呼叫處理器 IvocationHandler handler = new InvocationHandlerImpl(…); 2、通過為Proxy類指定ClassLoader物件和一組interface建立動態代理類 Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…}); 3、通過反射機制獲取動態代理類的建構函式,其引數型別是呼叫處理器介面型別 Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class}); 4、通過建構函式建立代理類例項,此時需將呼叫處理器物件作為引數被傳入 Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler)); 為了簡化物件建立過程,Proxy類中的newInstance方法封裝了2~4,只需兩步即可完成代理物件的建立。 生成的ProxySubject繼承Proxy類實現Subject介面,實現的Subject的方法實際呼叫處理器的invoke方法,而invoke方法利用反射呼叫的是被代理物件的的方法(Object result=method.invoke(proxied,args))