天天看點

設計模式之代理模式 靜态代理 動态代理設計模式之代理模式

設計模式之代理模式

靜态代理

package designpattern.proxy;

public class staticsubject implements Subject {
    private ConcretSubject concretSubject;

    @Override
    public void request() {
        concretSubject = new ConcretSubject();
        System.out.println("前置方法ss");
        concretSubject.request();
        System.out.println("後置方法ss");
    }
}
           

建立一個代理類同樣實作接口,在代理類中調用被代理的類的方法就實作了靜态代理。

動态代理

靜态代理我們需要為每一個代理的類建立一個代理,這會大大的增加代碼量,是以可以使用動态代理。

在動态代理中不需要手動建立代理類,隻需要編寫一個動态處理器,真正的代理對象有JDK在運作時為我們動态的建立。

JDK動态代理

第一種方法,建立一個實作InvocationHandler的類

定義一個接口

package designpattern.proxy;

public interface Subject {
    void request();
}
           

被代理的類

package designpattern.proxy;

public class ConcretSubject implements Subject {
    @Override
    public void request() {
        System.out.println("請求");
    }
}
           

代理方法

package designpattern.proxy;

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

public class JDKProxy implements InvocationHandler {
    private Object target;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置方法");
        Object o = method.invoke(target, args);
        System.out.println("後置方法");
        return o;
    }

    public Object getInstance(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}

           

實作

package designpattern.proxy;

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

public class client {
    public static void main(String[] args) {

        JDKProxy proxy = new JDKProxy();
        Subject instance = (Subject) proxy.getInstance(new ConcretSubject());
        instance.request();
       
        o.request();


    }
}
           

第二種方法:直接在Proxy.newProxyInstance()第三個參數中對方法進行增強。

package designpattern.proxy;

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

public class client {
    public static void main(String[] args) {

        Subject o = (Subject) Proxy.newProxyInstance(ConcretSubject.class.getClassLoader(), ConcretSubject.class.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("前置方法11");
                Object o = method.invoke(new ConcretSubject());
                System.out.println("後置方法22");
                return o;
            }
        });
        o.request();


    }
}
           

CGlib動态代理

JDK實作動态代理需要實作類通過接口定義業務方法,對于沒有接口的類,要想實作動态代理,就需要使用CGLib。

CGLib采用位元組碼技術,通過位元組碼技術為一個類建立一個子類,并在子類中采用方法攔截的技術攔截所有父類方法調用,順勢植入橫切邏輯。因為采用的繼承,是以不能對final修飾的類進行代理。

package designpattern.proxy;

public class cgclient {
    public static void main(String[] args) {
        CGProxy proxy = new CGProxy();
        Subject target = (Subject) proxy.getTarget(new ConcretSubject());
        target.request();
    }
}
           
package designpattern.proxy;

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

import java.lang.reflect.Method;

public class CGProxy implements MethodInterceptor {
    private Object target;

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("前置方法123");
        Object ob = method.invoke(target, args);
        System.out.println("後置方法123");
        return ob;
    }

    public Object getTarget(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
}