设计模式之代理模式

定义

代理一个对象 ,在对象前或后添加功能

静态代理
普通代理

代理对象和被代理对象实现同一个接口,代理对象引入被代理对象并调用其中方法

实现

public interface People {
    void run();
}

public class RealPeopel implements People {
    @Override
    public void run() {
        System.out.println("我在跑");
    }
}

public class ProxyPeople implements  People {
    public People people=null;
    public ProxyPeople(People people){
        this.people=people;
    }
    @Override
    public void run() {
        System.out.println("我是前置方法");            
            people.run();
        System.out.println("我是后置方法");
    }
}

public class Client {
    public static void main(String[] args) {
        ProxyPeople proxyPeople=new ProxyPeople(new RealPeopel());
        proxyPeople.run();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7oH5o0pc-1624368339861)(C:\Users\25443\AppData\Roaming\Typora\typora-user-images\image-20210621171021342.png)]

强制代理

再被代理对象中定义要使用的代理对象,通过被代理对象得到代理对象,进行代理(非指定的代理类无效)

实现

动态代理
public interface People {
    void run();
}


public class RealPeopel implements People {
    ProxyPeople proxyPeople=null;
    @Override
    public void run() {
        if (proxyPeople!=null){
            System.out.println("我在跑");
        }else {
            System.out.println("请使用正确的代理");
        }

    }

    public ProxyPeople getProxy(){
        return proxyPeople=new ProxyPeople(this);
    }
}

public class ProxyPeople implements  People {
    public People people=null;
    public ProxyPeople(People people){
        this.people=people;
    }
    @Override
    public void run() {
        System.out.println("我是前置方法");
            people.run();
        System.out.println("我是后置方法");
    }
}

public class Client {
    public static void main(String[] args) {
        RealPeopel realPeopel = new RealPeopel();
        realPeopel.run();
        ProxyPeople proxy = realPeopel.getProxy();
        proxy.run();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gQtf3YYq-1624368339865)(C:\Users\25443\AppData\Roaming\Typora\typora-user-images\image-20210621171916412.png)]

JDK动态代理

被代理类必须实现接口.

​ Handler类用于描述代理类的操作,必须事先InvocationHandler接口

public interface Subject {
    void run();
}

public class RealSubject implements Subject {
    public void run(){
        System.out.println("我在跑");
    }
}

public class Handler implements InvocationHandler {
    //被代理对象
    private Object target=null;

    public  Handler(Object o){
        target=o;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //可以再此处写各种代理操作
        System.out.println("哈哈哈我被代理啦 我是"+method.getName());
        return method.invoke(target,args);
    }
}

public class DynamicProxy<T> {
    //简单工厂返回代理对象
    public static <T>T newproxyInstance(ClassLoader classLoader, Class<?>[] interfaces, InvocationHandler handler){
        return (T) Proxy.newProxyInstance(classLoader,interfaces,handler);
    }
}

public class ObjectDynamicProxy extends DynamicProxy {
    //针对具体业务的动态代理
    public  static <T>T newProxyInstance(Object object){
        ClassLoader classLoader = object.getClass().getClassLoader();
        Class<?>[] interfaces = object.getClass().getInterfaces();
        Handler handler = new Handler(object);
        return (T) Proxy.newProxyInstance(classLoader,interfaces,handler);
    }
}

//测试类
public class Client {
    public static void main(String[] args) {
        Subject subject = new RealSubject();
        Subject proxy = ObjectDynamicProxy.newProxyInstance(subject);
        proxy.run();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KEfOs1fX-1624368339867)(C:\Users\25443\AppData\Roaming\Typora\typora-user-images\image-20210621160539788.png)]

CGlib动态代理

被代理类不需要实现接口

jdk创建对象的速度远大于cglib,这是由于cglib创建对象时需要操作字节码。cglib执行速度略大于jdk,所以比较适合单例模式。另外由于CGLIB的大部分类是直接对Java字节码进行操作,这样生成的类会在Java的永久堆中。如果动态代理操作过多,容易造成永久堆满,触发OutOfMemory异常。spring默认使用jdk动态代理,如果类没有接口,则使用cglib。

//和Handler有点相似
public class CglibProxy implements MethodInterceptor {

    // 根据一个类型产生代理类,此方法不要求一定放在MethodInterceptor中
    public Object CreatProxyedObj(Class<?> clazz) {
        Enhancer enhancer = new Enhancer();
        //继承被代理类
        enhancer.setSuperclass(clazz);
        //设置回调
        enhancer.setCallback(this);
        //生成代理类  在调用代理类中方法时会被我们实现的方法拦截器进行拦截
        return enhancer.create();
    }
    //Cglib使用的是继承机制 代理对象继承了被代理对象。所以才可以代理
    /**
     *
     * @param o 被代理对象
     * @param method   代理对象方法  子类方法
     * @param objects  方法参数
     * @param methodProxy  被代理对象方法 父类方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("我是前置方法");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("我是后置方法");
        return invoke;
    }
}

public class RealSubject  {
    public void run(){
        System.out.println("我在跑");
    }
}

public class Client {
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        RealSubject o = (RealSubject) cglibProxy.CreatProxyedObj(RealSubject.class);
        o.run();
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKG1K6Ir-1624368339869)(C:\Users\25443\AppData\Roaming\Typora\typora-user-images\image-20210621165912107.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值