Spring aop利用jdk的InvocationHandler產生動態代理
阿新 • • 發佈:2019-02-18
筆記之用……
首先有一個介面UserService
package com.spring.test;
import org.springframework.stereotype.Component;
@Component
public interface UserService {
public void createUser();
public void deleteUser();
public void updateUser(int id);
}
UserDao實現UserService
package com.spring.test; import org.springframework.stereotype.Component; @Component public class UserDao implements UserService { public void createUser() { System.out.println("user saved..."); } public void deleteUser(){ System.out.println("delete user..."); } public void updateUser(int id){ System.out.println("update user..."); } }
想要在這些方法執行的時候加一些業務邏輯,如公共日誌或者計算方法執行前後的時間等,將程式碼以切面的形式切入到方法中,此時可以用動態代理來實現,
aop的動態代理底層是用jdk的動態代理實現的proxy和InvocationHandler,需實現 java.lang.reflect.InvocationHandler
首先定義一個LogInteceptor來實現InvocationHandler:
package com.spring.log; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Calendar; import java.util.Date; /***************** * 日誌類 * * @author Administrator * */ public class LogInteceptor implements InvocationHandler{ private Object target;//被代理的物件 public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeMethod(method);//在方法執行前所要執行的業務邏輯 long starttime=System.currentTimeMillis(); method.invoke(target, args); long result=System.currentTimeMillis()-starttime; System.out.println("執行時間為:"+result+"毫秒"); afterMethod(method);//在方法執行後所要執行的業務邏輯 return null; } public void beforeMethod(Method m){ System.out.println(m.getName()+"執行before...."); } public void afterMethod(Method m){ System.out.println(m.getName()+"執行after..."); } }
然後用JUnit來進行測試
package com.junit.test; import java.lang.reflect.Proxy; import com.spring.log.LogInteceptor; import com.spring.test.UserDao; import com.spring.test.UserService; public class Test { @org.junit.Test public void testProxy(){ UserDao userDao=new UserDao();//被代理的物件 LogInteceptor logInteceptor=new LogInteceptor();//獲取日誌的InvocationHandler logInteceptor.setTarget(userDao);//把被代理的物件設為userDao //設定代理物件,引數1:被代理物件的classloader,引數2:被代理物件所實現的介面(該物件必須要實現介面,不然無法產生代理),引數3:指定處理的InvocationHandler UserService userService=(UserService)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), new Class[]{UserService.class}, logInteceptor); userService.createUser();//執行方法 userService.deleteUser();//執行方法 userService.updateUser(1001);//執行方法 } }
執行結果:
createUser執行before....
user saved...
---執行時間為:0毫秒
createUser執行after...
deleteUser執行before....
delete user...
---執行時間為:0毫秒
deleteUser執行after...
updateUser執行before....
update user...
---執行時間為:0毫秒
updateUser執行after...
接下來來點實際的..........................
定義一個LogInterceptor,讓dao裡的方法在執行的前後執行某些特定的方法
package com.spring.log;
public class LogInterceptor {
public void beforeMethod(){
System.out.println("方法執行前執行");
}
public void afterMethod(){
System.out.println("方法執行後執行");
}
}
定義的beforeMethod和afterMethod在applicationContext.xml裡用aop配置
<bean id="mylog" class="com.spring.log.LogInterceptor"></bean>
<aop:config>
<aop:aspect id="log" ref="mylog">
<aop:pointcut expression="execution (* com.spring.test.*.*(..))" id="point" /><!--切入點-->
<aop:before method="beforeMethod" pointcut-ref="point"/><!-- 定義方法before前執行自己定義的beforeMethod -->
<aop:after method="afterMethod" pointcut-ref="point"/><!-- 定義方法after後執行自己定義的afterMethod -->
</aop:aspect>
</aop:config>
當然還可以配置
<aop:around method=""/>
<aop:after-returning method=""/>
<aop:after-throwing method=""/>
最後用JUnit測試:
@org.junit.Test
public void Test(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = (UserService) ctx.getBean("userDao");
service.createUser();
}
執行結果:
方法執行前執行
user saved...
方法執行後執行