spring 動態代理
阿新 • • 發佈:2018-12-17
利用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))