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

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值