• 代理


    其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该 地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有 专长,可以替我们进行操作,表达我们的想法。先来看看关系图:

    代理模式的应用场景:

    如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

    1、修改原有的方法来适应。这样违反了"对扩展开放,对修改关闭"的原则。

    2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

    使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

    普通代理模式事例:

    Moveable.java

    package proxy;

     

    public interface Moveable {

        void move();

        

    }

    Tank.java

     

    //Tank实现Moveable方法

    public class Tank implements Moveable {

        @Override

        public void move() {

                System.out.println("Tank Moving...");}}

    Client.java    

    package proxy;

    public class Client {

        public static void main(String[] args) throws Exception {

            Tank t = new Tank();

            InvocationHandler h = new TimeHandler(t);

            Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class, h);

            m.move();}}

    //可以对任意的对象、任意的接口方法,实现任意的代理

    动态代理的设计原理:

     客户端调用代理,代理的构造方法接收一个Handler对象,客户端调用代理的各个方法时,代理的相应方法会把调用请求转发给Handler对象,Handler对象又把请求分发给目标的响应方法。 
    实现类似Spring的可配置的AOP框架 
    思路:工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。ProxyFactoryBean充当封装生成动态代理的工厂。 

    InvocationHandler.java    

    package proxy;

     

    import java.lang.reflect.Method;

     

    public interface InvocationHandler {

        public void invoke(Object o, Method m);

    }

    Proxy.java    

     

    public class Proxy {

        public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception { //JDK6 Complier API, CGLib, ASM

            String methodStr = "";

            String rt = " ";//wimdows中的换行符。

            

            Method[] methods = infce.getMethods();

            for(Method m : methods) {

                methodStr += "@Override" + rt +

                             "public void " + m.getName() + "() {" + rt +

                             " try {" + rt +

                             " Method md = " + infce.getName() + ".class.getMethod("" + m.getName() + "");" + rt +

                             " h.invoke(this, md);" + rt +

                             " }catch(Exception e) {e.printStackTrace();}" + rt +

                            

                             "}";

            }

            

            String src =

                "package proxy;" + rt +

                "import java.lang.reflect.Method;" + rt +

                "public class $Proxy1 implements " + infce.getName() + "{" + rt +

                " public $Proxy1(InvocationHandler h) {" + rt +

                " this.h = h;" + rt +

                " }" + rt +

                

                

                " proxy.InvocationHandler h;" + rt +

                                

                methodStr +

                "}";

            String fileName =

                "D:/workspace4java/MyJavaDesign/src/proxy/$Proxy1.java";

            File f = new File(fileName);

            FileWriter fw = new FileWriter(f);

            fw.write(src);

            fw.flush();

            fw.close();

            

            //compile编译过程

            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

            StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);

            Iterable units = fileMgr.getJavaFileObjects(fileName);

            CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);

            t.call();

            fileMgr.close();

            

            //load into memory and create an instance

            URL[] urls = new URL[] {new URL("file:/" + "D:/workspace4java/MyJavaDesign/src/")};

            URLClassLoader ul = new URLClassLoader(urls);

            Class c = ul.loadClass("proxy.$Proxy1");

            System.out.println(c);

            

            Constructor ctr = c.getConstructor(InvocationHandler.class);

            Object m = ctr.newInstance(h);

            //m.move();

     

            return m;

        }

    }

    TimeHandler.java    

    public class TimeHandler implements InvocationHandler{

        private Object target;

        public TimeHandler(Object target) {

            super();

            this.target = target;

        }

        @Override

        public void invoke(Object o, Method m) {

            long start = System.currentTimeMillis();

            System.out.println("starttime:" + start);

            System.out.println(o.getClass().getName());

            m.invoke(target);

            long end = System.currentTimeMillis();

            System.out.println("time:" + (end-start));

        }

     

    }

    Java的CGLib动态代理(这里没有代码需要自己动手)

    CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并顺势织入横切逻辑。

    public class BookFacadeImpl {

    public void addBook() {

    System.out.println("增加图书方法。。。");

    }

    }

    CGLib动态代理

    1.  
    2. /**
    3. * 使用cglib动态代理
    4. */
    5. public class BookFacadeCglib implements MethodInterceptor {
    6. private Object target;
    7.  
    8. /**
    9. * 创建代理对象
    10. * @param target
    11. * @return
    12. */
    13. public Object getInstance(Object target) {
    14. this.target = target;
    15. Enhancer enhancer = new Enhancer();
    16. // 设置需要创建子类的类
    17. enhancer.setSuperclass(this.target.getClass());
    18. // 回调方法
    19. enhancer.setCallback(this);
    20. // 通过字节码技术动态创建子类实例
    21. return enhancer.create();
    22. }
    23.  
    24. @Override
    25. // 回调方法 ,拦截所有的父类方法调用
    26. public Object intercept(Object obj, Method method, Object[] args,
    27. MethodProxy proxy) throws Throwable {
    28. System.out.println("事物开始");
    29. Object result = proxy.invokeSuper(obj, args); // 通过代码类调用父类中的方法
    30. System.out.println("事物结束");
    31. return result;
    32. }
    33.  
    34. }

     

    BookFacadeCglib cglib=new BookFacadeCglib();

    BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl());

    bookCglib.addBook();


    最终运行的结果如下:

    事物开始

    增加图书方法。。。

    事物结束

    注:加入cglib和asm的jar包。CGGlib创建的代理对象要比JDK的性能高很多,但是创建时所花费的时间却比JDK动态代理要多。所以对于singleton的代理对象或者具有实例池的代码,由于无须频繁创建代码对象,用CGLib比较合适。

    也就是生命周期长的实例用CGLib比较合适。

  • 相关阅读:
    UML建模之时序图(Sequence Diagram)
    UML统一建模语UML2和EnterpriseArchitect
    FTP服务器的搭建
    Ubuntu下Apache重启错误:Could not reliably determine解决
    JSP的优势 和劣势 与php的比较
    [置顶] Ajax 初步学习总结
    pv ticketlock解决虚拟环境下的spinlock问题
    Tomcat从零开始(十)Loader
    HDU 4740 The Donkey of Gui Zhou (模拟)
    关于cvScalar的那些事
  • 原文地址:https://www.cnblogs.com/jiumao/p/7136418.html
Copyright © 2020-2023  润新知