zoukankan      html  css  js  c++  java
  • Spring AOP 本质(4)

    这一主要看看Spring AOP是如何实现通知包围的。
     
    Spring AOP包围通知在功能上和前置通知加后置通知类似,但还是有区别的:包围通知可以修改返回值,还可以阻止、替换目标方法的执行。
     
    Spring里的包围通知是实现MethodInterceptor接口的拦截器。
     
    Spring包围通知有着很广泛的应用,比如远程代理和事务管理,都是由拦截器完成。另外,拦截器也是剖析程序运行的好方法。
     
    下面利用Spring AOP包围通知实现监控业务方法的执行运行过程耗时情况。
     
    /** 
    * 业务组件 
    */
     
    public class WorkerBean { 

        public void doSomeWork(int noOfTimes) { 
            for(int x = 0; x < noOfTimes; x++) { 
                work(); 
            } 
        } 
         
        private void work() { 
            System.out.print(""); 
        } 
    }
     
    import java.lang.reflect.Method; 

    import org.aopalliance.intercept.MethodInterceptor; 
    import org.aopalliance.intercept.MethodInvocation; 
    import org.springframework.util.StopWatch; 

    /** 
    * 拦截器,实现方法包围通知 
    */
     
    public class ProfilingInterceptor implements MethodInterceptor { 

        public Object invoke(MethodInvocation invocation) throws Throwable { 
            //启动一个 stop watch 
            StopWatch sw = new StopWatch(); 
            //运行计时器 
            sw.start(invocation.getMethod().getName()); 
            //执行业务方法 
            Object returnValue = invocation.proceed(); 
            //停止计时器 
            sw.stop(); 
            //垃圾信息输出 
            dumpInfo(invocation, sw.getTotalTimeMillis()); 
            //返回业务方法返回值 
            return returnValue; 
        } 

        /** 
         * 垃圾信息输入方法,实际上输出的是方法运行的计时信息 
         */
     
        private void dumpInfo(MethodInvocation invocation, long ms) { 
            //获取被调用方法 
            Method m = invocation.getMethod(); 
            //获取被调用方法所属的对象 
            Object target = invocation.getThis(); 
            //获取被调用方法的参数 
            Object[] args = invocation.getArguments(); 

            System.out.println("所执行的方法: " + m.getName()); 
            System.out.println("对象的类型: " + target.getClass().getName()); 

            System.out.println("方法的参数:"); 
            for (int x = 0; x < args.length; x++) { 
                System.out.print("    > " + args[x]); 
            } 
            System.out.print(" "); 

            System.out.println("抓取方法运行的时间: " + ms + " ms"); 
        } 
    }
     
    import org.springframework.aop.framework.ProxyFactory; 

    /** 
    * 客户端测试方法 
    */
     
    public class ProfilingExample { 

        public static void main(String[] args) { 
            //创建代理对象 
            WorkerBean bean = getWorkerBean(); 
            //在代理对象上调用业务方法 
            bean.doSomeWork(10000000); 
        } 

        /** 
         * 代理对象工厂 
         */
     
        private static WorkerBean getWorkerBean() { 
            //创建目标对象 
            WorkerBean target = new WorkerBean(); 
            //构建代理对象工厂 
            ProxyFactory factory = new ProxyFactory(); 
            factory.setTarget(target); 
            factory.addAdvice(new ProfilingInterceptor()); 

            //生产一个代理对象 
            return (WorkerBean)factory.getProxy(); 
        } 
    }
     
    运行结果:
    - Using JDK 1.4 collections 
    所执行的方法: doSomeWork 
    对象的类型: com.apress.prospring.ch6.profiling.WorkerBean 
    方法的参数: 
        > 10000000 
    抓取方法运行的时间: 3453 ms 

    Process finished with exit code 0
     
    从输出的结果中,可以看到程序方法调用的方法名、参数、所属类,以及执行方法所耗费的时间。
     
    另外说一下org.springframework.util.StopWatch类,这是个计时器类,此工具类主要可以获取计时器类start()和stop()两次方法调用间的时间。具体可以查看Spring的API文档。另外,我也在apache commons 包里面也有org.apache.common.lang.time.StopWatch。

    http://lavasoft.blog.51cto.com/62575/75342/

  • 相关阅读:
    谷粒商城学习——P52商品服务-API-三级分类-新增效果
    验证码爆破总结
    利用crawlergo-to-xray实现自动化漏洞被动扫描平台搭建
    数据导入经验总结
    SQL实现2个日期之间的工作日数(MySQL)(转)
    MySQL查询所有表的数据量
    crontab定时配置(转)
    SQLyog还原会话失败
    Nginx以xxx开头的转发
    mysql备份shell脚本
  • 原文地址:https://www.cnblogs.com/softidea/p/5789790.html
Copyright © 2011-2022 走看看