• 代理模式-你不并知道我的存在


    代理模式是对象的结构型模式,代理模式给某一个对象提供了一个代理对象。并由代理对象控制对原对象的引用。它的特征代理类与目标类有相同的接口,而且代理类与目标类之间通常存在关联关系。含有目标类的引用。以至于代理类可以控制目标对象。替它完毕它的方法:预处理消息、过滤消息、把消息转发给目标类。以及事后处理消息等。

     

    依照代理的创建时期,代理类能够分为两种:


    静态代理:

    UserManager接口:

    public interface UserManager {
    
             public void addUser(String userId, String userName); //加入用户方法
    
             public String findUser(String userId); //删除用户方法
    
    }
    


    UserManagerImpl类:

    public class UserManagerImpl implements UserManager { 
    
    //用户加入
    
             public void addUser(String userId, String userName) {            
    
                       try {
                                System.out.println("用户ID" + userId);                   
    
                       }catch(Exception e) {
    
                                e.printStackTrace();                   
    
                                throw new RuntimeException();
    
                       }        
             }        
    
    //用户查询 
    
             public String findUser(String userId) {
    
                       System.out.println("用户ID" + userId);
    
                       return "张三";
    
             }

     

    UserManagerImplProxy代理类:

          private UserManager userManager;  //含有目标类对象的引用         
    
             public UserManagerImplProxy(UserManager userManager) {
    
                       this.userManager = userManager;
             }         
             public void addUser(String userId, String userName) {
    
                       try {
                                System.out.println("開始加入-->>加入用户ID" + userId);
    
                                userManager.addUser(userId, userName);
    
                                System.out.println("成功加入-->>addUser()");
    
                       }catch(Exception e) {
    
                                e.printStackTrace();
    
                                System.out.println("加入失败-->>addUser()");
                       }        
             } 
    
    public String findUser(String userId) {
    
                       return null;    //此处不实现,若是实现,其方式同add方法
    
             }
    
     


    client调用:

    public class Client {
             public static void main(String[] args) {            
                       UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
                       userManager.addUser("0001", "张三");
             }
    
    }
    

     

    观察以上代码。能够发现每个代理类仅仅能为一个接口服务(public UserManagerImplProxy(UserManageruserManager))。这样一来须要建立大量的代理类。

    而且,全部的代理操作除了调用的方法不一样之外,其它的操作都一样。比如,findUser中若是实现,将反复使用System.out.println("開始加入-->>加入用户ID"+ userId); System.out.println("成功加入-->>addUser()"); System.out.println("加入失败-->>addUser()");反复的代码出现多次对于开发者来说是绝对不同意的,那么该怎么解决问题呢?最好的办法那就是通过一个代理类完毕所有的代理功能,这就涉及到了动态代理。

     

    动态代理:在程序执行时,运用反射机制动态创建而成。

     

    代码演示样例:

    UserManager接口:

    public interface UserManager { 
    
             public void addUser(String userId, String userName);
             public String findUser(String userId);
    
    }
    

    真正实现类:

    public class UserManagerImpl implements UserManager { 
    
             public void addUser(String userId, String userName) {            
    
                       try {
                                System.out.println("用户ID" + userId);          
    
                       }catch(Exception e) {
                                e.printStackTrace();     
                                throw new RuntimeException();
                       }        
             }
    
             public String findUser(String userId) {
                       System.out.println("用户ID" + userId);
                       return "张三";
    
             }
    

    动态代理代理类:

    public class LogHandler implements InvocationHandler {         
    
             private Object targetObject;
    
             //依据传过来的对象生成代理
    
             public Object newProxyInstance(Object targetObject) {
    
                       this.targetObject = targetObject;
    
                       return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
    
                                    targetObject.getClass().getInterfaces(), this);    //
             }         
    
             public Object invoke(Object proxy, Method method, Object[] args)
    
                                throws Throwable {
    
                       System.out.println("start-->>" + method.getName());
    
                       for (int i=0; i<args.length; i++) {
    
                                System.out.println(args[i]);
                       }
    
                       Object ret = null;
                       try {
                                //调用目标方法
    
                                ret = method.invoke(targetObject, args);
    
                                System.out.println("success-->>" + method.getName()); 
    
                       }catch(Exception e) {
    
                                e.printStackTrace();
    
                                System.out.println("error-->>" + method.getName());
    
                                throw e;
                       }
                       return ret;
             }
    }
    

    动态代理包括一个接口和一个类:

    InvocationHandler接口:

     

    Public static Object newProxyInstance(ClassLoader loader,Class<?

    >[]interfaces,InvocatiocHandler h) throws IllegalArgumentException



    返回一个指定接口的代理类实例,该接口能够将方法调用指派到指定的调用处理程序。

     

    參数:

            Loader:定义代理类的类载入器

            Class<?>[]interfaces:得到所有的接口      

    InvocationHandlerh:得到InvocationHandler接口的子类实例 

     

    Proxy类:动态的声明出一个代理对象,为什么样生成出代理呢?这个类必须实现了接口才行。假设这个类没有实现接口,不能生成代理。说白了他就是依据这个接口在内存中建立出一个类。    

     

    client调用:

    public class Client {
    
             public static void main(String[] args) {
    
                       LogHandler logHandler = new LogHandler();
    
                       UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl());
    
                       userManager.addUser("001","猪猪");            
    
             }
    
    }
    


    总结:

    动态代理相对于静态代理来说更加灵活了。为什么呢?比如重载和覆盖。重载属于静态的结构。当定义两个參数不一样的method方法时,我们在调用的时候。须要指定method方法的參数。

    也就是我们在编译的时候就指定好该调谁了。而覆盖的功能更强,由于它的方法调用不是静态的时候进行绑定,也不是说我写代码编译的时候就指定好我应该调谁。而是在执行的时候决定它是什么类型就调谁。


    正常情况下。我们须要创建非常多的代理类,假设我还有其它的manager也须要完毕这些功能,那么她还须要创建代理类,来完毕。动态代理则不用,由于这个proxySubject这个类不须要自己创建,他在内存中创建。所以你压根就不知道代理类的存在。当然代理类的个数。也不须要你关心。


  • 相关阅读:
    Git的环境搭建
    AmazeUI HTML元素
    AmazeUI布局
    AmazeUI基本样式
    Bash简介
    Linux下拷贝目录和删除
    linux下的定时任务
    缓存
    隔离
    DEDECMS使用SQL命令批量替换语句
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6920920.html
Copyright © 2020-2023  润新知