Spring aop利用jdk的InvocationHandler產生動態代理

筆記之用……


首先有一個接口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...
方法執行後執行



如果要獲取執行的類和方法,可以接一個JoinPoint參數,用來獲取執行的方法名

package com.spring.log;

import org.aspectj.lang.JoinPoint;

public class LogInterceptor {
	
	public void beforeMethod(JoinPoint point){
		System.out.println("方法執行前執行");
		//System.out.println(point.getTarget());//獲取類com.spring.test.UserDao@15e0873
		//System.out.println(point.getSignature().getName());//獲取方法名
		System.out.println(point.getTarget()+"類的"+point.getSignature().getName()+"方法執行!!!");
	}
	
	public void afterMethod(JoinPoint point){
		System.out.println("方法執行後執行");
		System.out.println(point.getTarget()+"類的"+point.getSignature().getName()+"方法執行完畢!!!");
	}

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