• 学习准备2


    23种设计模式

    8> 代理模式

    这篇文章写的较简洁易懂:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

    分为静态代理、动态代理。动态代理又有两种实现:JDK动态代理、cglib动态代理

    静态代理:

    interface Subject {
        void request();
    }
    
    class RealSubject implements Subject {
        public void request(){
            System.out.println("RealSubject");
        }
    }
    
    class Proxy implements Subject {
        private Subject subject;
    
        public Proxy(Subject subject){
            this.subject = subject;
        }
        public void request(){
            System.out.println("begin");
            subject.request();
            System.out.println("end");
        }
    }
    
    public class ProxyTest {
        public static void main(String args[]) {
            RealSubject subject = new RealSubject();
            Proxy p = new Proxy(subject);
            p.request();
        }
    }

    静态代理实现中,一个委托类对应一个代理类,代理类在编译期间就已经确定。

    * 动态代理(JDK动态代理)

    interface Subject {
        void request();
    }
    
    class RealSubject implements Subject {
        public void request(){
            System.out.println("RealSubject");
        }
    }

    public class DynamicProxy implements InvocationHandler {

     

    private Object obj;

     

    public DynamicProxy() {

     

    }

     

    public DynamicProxy(Object obj) {

    this.obj = obj;

    }

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

     

    System.out.println("before calling method");

    method.invoke(obj, args);

    System.out.println("after calling method");

    return null;

    }

     

    客户端

    public class Client {

     

    public static void main(String[] args) {

    Subject sub = new SubjectImpl();

    //这里指定被代理类  

    InvocationHandler ih = new DynamicProxy(sub);

    Class<?> cla = sub.getClass();

     

       //以下是一次性生成代理 

    Subject subject = (Subject) Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), ih);

     

      //这里可以通过运行结果证明subject是Proxy的一个实例,这个实例实现了Subject接口  

            System.out.println(subject instanceof Proxy);  

            

            System.out.println("subject的Class类是:"+subject.getClass().toString());  

            

            System.out.print("subject中的属性有:");  

            

            Field[] field = subject.getClass().getDeclaredFields();

            for(Field s:field){

            System.out.println(s.getName());

            }

            

            System.out.print(" "+"subject中的方法有:");  

            

            Method[] method=subject.getClass().getDeclaredMethods();  

              

            for(Method m:method){  

                System.out.print(m.getName()+", ");  

            }  

              

            System.out.println(" "+"subject的父类是:"+subject.getClass().getSuperclass());  

              

            System.out.print(" "+"subject实现的接口是:");  

              

            Class<?>[] interfaces=subject.getClass().getInterfaces();  

              

            for(Class<?> i:interfaces){  

                System.out.print(i.getName()+", ");  

            }  

      

            System.out.println(" "+"运行结果为:");  

            subject.method();  

        }  

    }

    JDK动态代理中包含一个类和一个接口: 
    InvocationHandler接口: 
    public interface InvocationHandler { 
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 

    参数说明: 
    Object proxy:指被代理的对象。 
    Method method:要调用的方法 
    Object[] args:方法调用时所需要的参数 

    可以将InvocationHandler接口的子类想象成一个代理的最终操作类

    Proxy类: 
    Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法: 
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 
    InvocationHandler h) 
                                   throws IllegalArgumentException 
    参数说明: 
    ClassLoader loader:类加载器 
    Class<?>[] interfaces:得到全部的接口 
    InvocationHandler h:得到InvocationHandler接口的子类实例 

    Ps:类加载器 
    在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器; 
    Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的; 
    Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jrelibext目录中的类; 
    AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。 

    动态代理 
    与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。 

     

    动态代理(cglib动态代理)

     

    但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。 

    Cglib动态代理 
    JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。 

    示例:

    public class CglibProxy implements MethodInterceptor{

     

    private Enhancer enhancer = new Enhancer();

     

    public Object getProxy(Class clazz){

    //设置需要创建子类的类  

    enhancer.setSuperclass(clazz);

    enhancer.setCallback(this);

    //通过字节码技术动态创建子类实例  

    Object obj = enhancer.create();

    return obj;

    }

    @Override

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

    System.out.println("前置代理");

    Object result = proxy.invokeSuper(obj, args);

    System.out.println("后置代理");

    return result;

    }

    }

    测试类

    public class CglibTest {

     

    public static void main(String[] args) {

    CglibProxy proxy = new CglibProxy();

    //通过生成子类的方式创建代理类 

    SubjectImpl sub = (SubjectImpl) proxy.getProxy(SubjectImpl.class);

    sub.method();

    }

    }

  • 相关阅读:
    禅道安装
    logstash将配置写在多个文件
    原版Filebeat+ELK
    Filebeat+ELK部署文档
    A-2---Jenkins安装
    Linux ftp服务器搭建
    linux 网络命令
    yum安装时出现No more mirrors to try.
    kvm 修改虚拟机密码
    NFS安装
  • 原文地址:https://www.cnblogs.com/-wyl/p/7161277.html
Copyright © 2020-2023  润新知