`
king_tt
  • 浏览: 2123298 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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()+"方法执行完毕!!!");
	}

}



 



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics