zoukankan      html  css  js  c++  java
  • java动态代理框架

     
           java动态代理是一个挺有意思的东西,他有时候可以被使用的很灵活。像rpc的调用,调用方只是定义的一个接口,动态代理让他匹配上对应的不同接口;mybatis内部的实现,编码时,只是实现了mapper层的接口和sql的xml的配置,动态代理把他们连起来。记得之前在一家公司,他们使用thrift做rpc的解决方案,每个项目都得管理thrift的连接和关闭,代码考来考去,在spring下还得不断new对象。后来参照mybatis的实现方式,使用动态代理,做成spring注入的方式,方便很多,程序员只需要加些配置就好了。
     
         先来一个动态代理的简单实例:
    /**
     * Created by sten on 7/12/16.
     */
    public interface Person {
    
        void eat() ;
    }
     
    /**
     * Created by sten on 7/12/16.
     */
    public class Chinese implements Person {
    
        @Override
        public void eat() {
            System.out.print("eat fish.");
        }
    }
     
    /**
     * Created by sten on 7/12/16.
     */
    public class InvocationTest implements InvocationHandler {
    
        private Person person ;
    
        public InvocationTest(Person person) {
            this.person = person ;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(person, args);
        }
    }
     
    /**
     * Created by sten on 7/12/16.
     */
    public class Main {
    
        public static void main(String[] args) {
    
            Chinese chinese = new Chinese() ;
    
            Person person = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),
                    new Class[]{Person.class},
                    new InvocationTest(chinese));
    
            person.eat();
        }
    
    }
     
    这是一般动态代理的范式,Chinese代理Person的实现,接口person每个方法的调用,实际执行的方法是InvocationTest.invoke, 当然,还有动态代理还有其他实现方式。
     
    这里实现简单实现下mybatis的动态代理:
     
    假设解析完mapper和xml,知道每个mapper的方法对应的sql了,通过类名和方法名,就可以执行sql
     
     
    /**
     * Created by sten on 7/12/16.
     */
    public class SqlMap {
    
        private Map<String, String> map = new HashedMap() ;
    
        public SqlMap() {
            map.put("Class1.method1","select sql1") ;
            map.put("Class1.method2","delete sql1") ;
            map.put("Class1.method3","update sql1") ;
            map.put("Class1.method4","insert sql1") ;
            map.put("Class2.method1","select sql2") ;
            map.put("Class2.method2","delete sql2") ;
            map.put("Class2.method3","update sql2") ;
            map.put("Class2.method4","insert sql2") ;
        }
    
        public String getSql(String classNameMethodName) {
            return  map.get(classNameMethodName) ;
        }
    
    }
     
    假设定义的一个mapper
     
    /**
     * Created by sten on 7/12/16.
     */
    public interface Class1 {
    
        String method1() ;
    
        String method2() ;
    
        String method3() ;
    
        String method4() ;
    }

     
    InvocationHandler的实现
     
    /**
     * Created by sten on 7/12/16.
     */
    public class InvocationSql implements InvocationHandler {
    
        private Class interfaceObject ;
    
        private SqlMap sqlMap ;
    
        public InvocationSql(Class interfaceObject, SqlMap sqlMap) {
            this.interfaceObject = interfaceObject ;
            this.sqlMap = sqlMap ;
        }
    
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            String key = interfaceObject.getClass().getName() + "." + method.getName() ;
            String value = sqlMap.getSql(key) ;
    
            return value ;
        }
    }

     
    根据mapper接口生成对象
     
    /**
     * Created by sten on 7/12/16.
     */
    public class TargetProxy<T> {
    
        public T  getTarget(Class<T> interfaceObject, SqlMap sqlMap) {
    
            InvocationSql invocationSql = new InvocationSql(interfaceObject, sqlMap) ;
    
            return (T)newProxyInstance(interfaceObject.getClassLoader(),new Class[] {interfaceObject},
                    invocationSql) ;
        }
    
    }

     
    执行生成的对象
     
    /**
     * Created by sten on 7/12/16.
     */
    public class Bitis {
    
    
        public static void main(String[] args) {
    
            TargetProxy targetProxy = new TargetProxy() ;
    
            Class1 class1 = (Class1) targetProxy.getTarget(Class1.class, new SqlMap());
    
            class1.method1() ;
        }
    
    }
     
     
     
     
     
  • 相关阅读:
    BZOJ3518 : 点组计数
    BZOJ2217 : [Poi2011]Lollipop
    李洪强经典面试题40-可能碰到的iOS笔试面试题-C语言
    对AFN的二次封装
    李洪强经典面试题39-iOS 程序员 6 级考试(答案和解释)
    iOS五种本地缓存数据方式
    iOS开发网络篇—数据缓存
    iOS中的通知
    李洪强漫谈iOS开发[C语言-048]-打印平方表
    李洪强漫谈iOS开发[C语言-047]-数列求和
  • 原文地址:https://www.cnblogs.com/sten/p/5664911.html
Copyright © 2011-2022 走看看