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



  • 相关阅读:
    由js apply与call方法想到的js数据类型(原始类型和引用类型)
    ajax跨域
    悟透JavaScript(理解JS面向对象的好文章)
    Item 18: Understand the Difference between Function, Method, and Constructor Calls
    torch:hardsigmoid
    torch:CrossEntropy是个构造器,所以loss = torch.nn.CrossEntropyLoss()(output, target)这么写就对了
    检查运行文件名称与模块名称是否重复。如果重复,需要将文件名称重新命名。
    a = np.r_[1:4,0,4] 这语法有点神奇
    lstm官方demo,有好几种输出的shape
    np.c_ 这个玩意儿不是个方法,而是返回一个类然后直接和后面的ndarry相乘。。。相当于concatenate(【】,dim)
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3050665.html
Copyright © 2020-2023  润新知