天天看点

设计模式之代理模式 静态代理 动态代理设计模式之代理模式

设计模式之代理模式

静态代理

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();
    }
}