Java 代理模式

1、靜態代理java

  一、經過繼承實現代理數組

  二、經過實現相同的接口進行代理dom

  例:ide

  接口this

//統一接口
public interface Moveable {
    
    public void move();

}
View Code

  被代理類spa

import java.util.Random;

public class Car implements Moveable{

    @Override
    public void move() {

        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽車正在行駛中.....");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            
    }

}
View Code

  代理類1代理

public class CarLogProxy implements Moveable {
    
    private Moveable m;

    public CarLogProxy(Moveable m) {
        super();
        this.m = m;
    }


    @Override
    public void move() {
        
        System.out.println("日誌開始。。。。。");
        m.move();
        System.out.println("日誌結束。。。。。");

    }

}
View Code

  代理類2日誌

public class CarTimeProxy implements Moveable {
    
    private Moveable m;
    

    public CarTimeProxy(Moveable m) {
        super();
        this.m = m;
    }

    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽車開始行駛。。。。。");
        
        m.move();
        
        long endtime = System.currentTimeMillis();
        System.out.println("汽車行駛結束。。。。。行駛時間("+(endtime - starttime)+")");

    }

}
View Code

  客戶端code

public class Client {

    public static void main(String[] args) {

        Car car = new Car();
        Moveable m = new CarTimeProxy(car);
        Moveable m1 = new CarLogProxy(m);
        
        m1.move();
        
    }

}
View Code

 

2、動態代理 (JDK動態代理)對象

Java動態代理類位於java.lang.reflect包下,通常主要涉及到如下兩個類:

(1) Interface InvocationHandler:該類中僅定義了一個方法

  public object invoke(Object obj, Method method, Object[] args)

  第一個參數obj通常是指代理類,method是被代理的方法,

  args爲該方法的參數數組。這個抽象方法在代理類中動態實現。

(2) Proxy:該類即爲動態代理類

  static Object newProxyInstance(ClassLoader loader, Class[] interfaces,

  InvocationHandler h):返回代理類的一個實例,返回後的代理類能夠看成

  被代理類使用(可以使用被代理類的在接口中聲明過的方法)

  例:

  接口

//統一接口
public interface Moveable {
    
    public void move();

}
View Code

  被代理類

import java.util.Random;

public class Car implements Moveable{

    @Override
    public void move() {

        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽車正在行駛中.....");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            
    }

}
View Code

  動態代理handler

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler {
    

    
    public TimeHandler(Object target) {
        super();
        this.target = target;
    }


    private Object target;
    
    /*
     * 參數:
     * proxy 被代理對象
     * method 被代理對象的方法
     * args 方法的參數
     * 
     * 返回值:
     * Object 方法的返回值
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] arg) throws Throwable {
        long starttime = System.currentTimeMillis();
        System.out.println("汽車開始行駛。。。。。");
        method.invoke(target);
        long endtime = System.currentTimeMillis();
        System.out.println("汽車行駛結束。。。。。行駛時間("+(endtime - starttime)+")");
        return null;
    }

}
View Code

  客戶端代碼

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {
        
        Car car = new Car();
        
        InvocationHandler h = new TimeHandler(car);
        
        Class<?> cls = car.getClass();
        
        /**
         * loader 類加載器
         * interfaces 實現接口
         * h InvocationHandler
         */
        Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
        
        m.move();

    }

}
View Code

 所謂Dynamic Proxy是這樣一種class:

它是在運行時生成的class

該class須要實現一組interface

使用動態代理類時,必須實現InvocationHandler接口

 

步驟:

一、建立一個實現接口InvocationHandler的類,它必須實現invoke方法。

二、建立被代理的類以及接口

三、調用Proxy的靜態方法,建立一個代理類

  newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

四、經過代理調用方法

 

CGLIB動態代理

 一、導入cglib包

 二、代理類實現   net.sf.cglib.proxy.MethodInterceptor接口

 三、代理類實現   intercept(Object obj, Method m, Object[] args, MethodProxy proxy) 方法。

被代理類

public class Train {
    
    public void move() {
        System.out.println("火車行駛中......");
    }

}
View Code

  代理類

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {
    
    private Enhancer enhancer = new Enhancer();
    
    public Object getProxy(Class clazz) {
        
        //設置建立子類的類
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
        
    }

    /**
     * 攔截全部目標類方法的調用
     * obj 目標類的實例
     * m 目標方法的反射對象
     * args 方法的參數
     * proxy 代理類的實例
     */
    @Override
    public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
        
        System.out.println("日誌開始....");
        //代理類調用父類的方法
        proxy.invokeSuper(obj, args);
        System.out.println("日誌結束....");
        return null;
    }

}
View Code

  客戶端

public class Client {

    public static void main(String[] args) {
        
        CglibProxy proxy = new CglibProxy();
        Train t = (Train)proxy.getProxy(Train.class);
        t.move();

    }

}
View Code

 

 

 

 

JDK動態代理

  一、只能代理實現了接口的類

  二、沒有實現接口的類不能實現JDK動態代理

 

CGLIB動態代理

  一、針對類來實現代理的。

  二、對指定目標產生一個子類,經過方法攔截技術攔截全部父類方法的調用。

相關文章
相關標籤/搜索