码迷,mamicode.com
首页 > 其他好文 > 详细

代理模式

时间:2018-12-19 13:03:15      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:artifact   str   jdk   模式   继承   etc   getc   分享图片   throwable   

讲代理模式之前,我们要先明白什么是“代理”

代理:简单来说就是将事情交给代替你去处理

代理分为 静态代理动态代理

静态代理

直接为每一个实现类写一个代替类

接口:

public interface IMath {
    int add(int n1, int n2);

    int sub(int n1, int n2);

    int mut(int n1, int n2);
}

实现类:

package com.nf147.ssm.springAOP.service;

public class Math implements IMath {
    @Override
    public int add(int n1, int n2) {
        int result = n1 + n2;
        System.out.println(n1 + "+" + n2 + "=" + result);
        return result;
    }

    @Override
    public int sub(int n1, int n2) {
        int result = n1 - n2;
        System.out.println(n1 + "-" + n2 + "=" + result);
        return result;
    }

    @Override
    public int mut(int n1, int n2) {
        int result = n1 / n2;
        System.out.println(n1 + "/" + n2 + "=" + result);
        return result;
    }
}

 

 代理类:

package com.nf147.ssm.springAOP.proxy;

import com.nf147.ssm.springAOP.service.IMath;
import com.nf147.ssm.springAOP.service.Math;

import java.util.Random;

// IMath的静态代理类
public class MathProxy implements IMath {

    IMath iMath = new Math();

    @Override
    public int add(int n1, int n2) {
        long start = System.currentTimeMillis();
        lazy();
        int result = iMath.add(n1, n2);
        Long span =  System.currentTimeMillis() - start;
        System.out.println("共用时:" + span);
        return result;
    }

    @Override
    public int sub(int n1, int n2) {
        long start = System.currentTimeMillis();
        lazy();
        int result = iMath.sub(n1, n2);
        Long span =  System.currentTimeMillis() - start;
        System.out.println("共用时:" + span);
        return result;
    }

    @Override
    public int mut(int n1, int n2) {
        long start = System.currentTimeMillis();
        lazy();
        int result = iMath.mut(n1, n2);
        Long span =  System.currentTimeMillis() - start;
        System.out.println("共用时:" + span);
        return result;
    }

    // 人为延时
    public void lazy(){
        try {
            int n = (int)new Random().nextInt(500);
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

测试:

// 静态代理
IMath math = new MathProxy();
@org.junit.Test
public void test01() {
   int n1 = 100, n2 = 5;
   math.add(n1, n2);
   math.sub(n1, n2);
   math.mut(n1, n2);
}

 

结果:

 技术分享图片

 这种模式的优点:客户端不需要知道实现类是什么,怎么做的,只需要知道代理就可以了

缺点:代理类和委托类继承了相同的接口,代理类通过委托类实现了相同的方法,使得出现了大量重复的代码,

如果接口增加一个方法,那么不仅仅是实现类要去实现这个方法,所有的代理类也要去实现这个方法,这就增加了代码的复杂度;

动态代理

动态代理又分为:JDK代理对象CGLib代理对象

JDBK代理对象:是java.lang.reflect.*包提供的方式,它必须借助于一个接口才能产生代理对象

代理类:

package com.nf147.ssm.springAOP.proxy;

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

// 动态代理类
public class DynamicProxy implements InvocationHandler {

    Object object;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        lazy();
        Object result = method.invoke(object,args);
        Long span = System.currentTimeMillis() - start;
        System.out.println("共用时:" + span);
        return result;
    }

    // 模拟延时
    public void lazy(){
        try {
            int n = (int)new Random().nextInt(500);
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

测试:

// 动态代理
    IMath math2 = (IMath) new DynamicProxy().getProxyObject(new Math());
    @org.junit.Test
    public void test02() {
        int n1 = 100, n2 = 5;
        math2.add(n1, n2);
        math2.sub(n1, n2);
        math2.mut(n1, n2);
    }

 

结果:

技术分享图片

 

 

 因为 JDK 动态代理必须要提供接口才能使用,在一些不能提供接口的环境中,它就不适用了

CGLIb动态代理

它是一个开源项目,是一个强大的,高性能的,高质量的Code生成类库,它可以在运行期扩展 Java 类和实现 Java 接口,

通俗说 cglib 可以在运行时动态生成字节码。

在使用前,要先去 https://mvnrepository.com/artifact/cglib/cglib/3.2.4 添加 cglib 包

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.4</version>
</dependency>

 代理类:

package com.nf147.ssm.springAOP.proxy;


import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;
import java.util.Random;

// CGLib
// 动态代理类
public class CGLibProxy implements MethodInterceptor {

    // 被代理的对象
    Object object;

    public Object getObject(Object object) {
        this.object = object;
        // 增强器,动态代码生成器
        Enhancer enhancer = new Enhancer();
        // 回调方法
        enhancer.setCallback((Callback) this);
        // 设置生成类的父类类型
        enhancer.setSuperclass(object.getClass());
        // 动态生成字节码并返回代理对象
        return enhancer.create();
    }

    // 拦截方法
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        long start = System.currentTimeMillis();
        lazy();

        // 调用方法
        Object result = methodProxy.invoke(object, args);
        Long span = System.currentTimeMillis() - start;
        System.out.println("共用时:" + span);
        return result;
    }

    // 模拟延时
    public void lazy() {
        try {
            int n = (int) new Random().nextInt(500);
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 

 测试:

@org.junit.Test
    public void test03() {
        Math math3 = (Math) new CGLibProxy().getObject(new Math());
        int n1 = 100, n2 = 5;
        math3.add(n1, n2);
        math3.sub(n1, n2);
        math3.mut(n1, n2);
    }

 

 结果:

技术分享图片

 

代理模式

标签:artifact   str   jdk   模式   继承   etc   getc   分享图片   throwable   

原文地址:https://www.cnblogs.com/wfhking/p/10141230.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!