zoukankan      html  css  js  c++  java
  • [置顶] 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...
    方法执行后执行



  • 相关阅读:
    如何快速生成API并进行测试
    如何开始使用接口自动化测试脚本
    一些网上密码学资源(转载)
    手把手硬件电路详细设计过程(转载)
    触发器(trigger)的作用???
    去面试字节跳动啦!
    2020年白领年终奖报告来了,平均值为7826元
    12 个顶级 Bug 跟踪工具
    接口的幂等性怎么设计?
    魔改一波合成大西瓜!代码已开源~
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3050665.html
Copyright © 2011-2022 走看看