• 6、动态代理


    在前面讲静态代理的时候说道它有一个缺陷:必须为每一个你想要进行代理的接口都设计一个静态的代理类。

    那么,有没有一种更加灵活的方案呢?这就是动态代理,即在运行时为特定接口动态的生成一个代理类对象。

    与动态代理密切相关的有两个东西:java.lang.reflect.InvocationHandler与java.lang.reflect.Proxy

    实现一个动态代理只需要做两个步骤的工作:①设计一个Handler类让其实现InvocationHandler接口;②调用Proxy.newProxyInstance(...)方法来得到一个代理类对象;

    第一步:

    package com.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.util.Date;
    
    public class RequestProxyHandler implements InvocationHandler {
        
        private Object proxied;
        public RequestProxyHandler(Object proxied) {
            this.proxied = proxied;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            
            //针对request方法作特殊处理:如果请求的当前时间在00:00:00~05:59:59之间,则不会执行实际的reques(...)方法
            if(method.getName().equals("request")){
                Date start = new Date(DateUtil.timeOfToday(0, 0, 0));
                Date end = new Date(DateUtil.timeOfToday(5, 59, 59));
                Date now = new Date();
                if(now.after(start)&&now.before(end)){
                    System.out.println("系统维护时间,禁止请求...");
                    return null;    //不会执行被代理对象的实际方法
                }
            }
            //使用反射来调用被代理的实际方法
            return method.invoke(proxied, args);    
        }
    }

    第二步:

     1 package com.proxy;
     2 
     3 import java.lang.reflect.Proxy;
     4 
     5 public class Test {
     6     
     7     public static void main(String[] args) {
     8         //创建一个被代理对象
     9         ISubject subProxied = new SubjectImpl();
    10         //将被代理对象传递到MyProxyHandler中,创建一个InvocationHandler对象来处理被代理对象
    11         ISubject sub = (ISubject) Proxy.newProxyInstance(SubjectImpl.class.getClassLoader(),
    12                 new Class[]{ISubject.class}, new RequestProxyHandler(subProxied));
    13         
    14         sub.request();
    15         int res = (int)sub.add(10, 20);
    16         System.out.println(res);
    17     }
    18 
    19 }

    下面是完整的代码:

     1 package com.proxy;
     2 
     3 import java.util.Calendar;
     4 import java.util.Date;
     5 
     6 public class DateUtil {
     7     
     8     public static long timeOfToday(int hour, int minute, int second){
     9         Calendar calendar = Calendar.getInstance();
    10         calendar.set(Calendar.HOUR_OF_DAY, hour);
    11         calendar.set(Calendar.MINUTE, minute);
    12         calendar.set(Calendar.SECOND, second);
    13         calendar.set(Calendar.MILLISECOND, 0);
    14         Date today = calendar.getTime();
    15         return today.getTime();
    16     }
    17 }
    public class DateUtil
    package com.proxy;
    
    public interface ISubject {
        
        public void request();
        public int add(int a, int b);
    
    }
    public interface ISubject
     1 package com.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 import java.util.Date;
     6 
     7 public class RequestProxyHandler implements InvocationHandler {
     8     
     9     private Object proxied;
    10     public RequestProxyHandler(Object proxied) {
    11         this.proxied = proxied;
    12     }
    13 
    14     @Override
    15     public Object invoke(Object proxy, Method method, Object[] args)
    16             throws Throwable {
    17         
    18         //针对request方法作特殊处理:如果请求的当前时间在00:00:00~05:59:59之间,则不会执行实际的reques(...)方法
    19         if(method.getName().equals("request")){
    20             Date start = new Date(DateUtil.timeOfToday(0, 0, 0));
    21             Date end = new Date(DateUtil.timeOfToday(5, 59, 59));
    22             Date now = new Date();
    23             if(now.after(start)&&now.before(end)){
    24                 System.out.println("系统维护时间,禁止请求...");
    25                 return null;    //不会执行被代理对象的实际方法
    26             }
    27         }
    28         //使用反射来调用被代理的实际方法
    29         return method.invoke(proxied, args);    
    30     }
    31 }
    public class RequestProxyHandler implements InvocationHandler
     1 package com.proxy;
     2 
     3 public class SubjectImpl implements ISubject {
     4 
     5     @Override
     6     public void request() {
     7         System.out.println("发送请求...");
     8     }
     9 
    10     @Override
    11     public int add(int a, int b) {
    12         return a + b;
    13     }
    14 
    15 }
    public class SubjectImpl implements ISubject
     1 package com.proxy;
     2 
     3 import java.lang.reflect.Proxy;
     4 
     5 public class Test {
     6     
     7     public static void main(String[] args) {
     8         //创建一个被代理对象
     9         ISubject subProxied = new SubjectImpl();
    10         //将被代理对象传递到MyProxyHandler中,创建一个InvocationHandler对象来处理被代理对象
    11         ISubject sub = (ISubject) Proxy.newProxyInstance(SubjectImpl.class.getClassLoader(),
    12                 new Class[]{ISubject.class}, new RequestProxyHandler(subProxied));
    13         
    14         sub.request();
    15         int res = (int)sub.add(10, 20);
    16         System.out.println(res);
    17     }
    18 
    19 }
    public class Test
  • 相关阅读:
    Windows CE Notification API的使用方法
    探讨如何成为技术团队管理者
    Android应用---基于NDK的samples例程hello-jni学习NDK开发
    在eclipse中配置android ndk的自动编译环境builders
    用javah 导出类的头文件, 常见的错误及正确的使用方法
    Android下NDK开发环境搭建
    Android系统修改硬件设备访问权限
    Android调试工具之ADB
    关于前端小白的一点小建议
    Vue.js简单实践
  • 原文地址:https://www.cnblogs.com/lj95801/p/5392689.html
Copyright © 2020-2023  润新知