[置顶] 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...
方法执行后执行