设计模式(一)--代理模式

设计模式是java基础中很重要的一部分,设计模式说白了就是之前的人总结出的套路,就像小说中那些武功秘籍、内功心法同样java

设计模式分为三大类:node

  一、建立型模式(5种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式设计模式

  二、结构型模式(7种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式数组

  三、行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式框架

中介者模式、解释器模式ide

  设计模式不该该死记硬背、更应该去融会贯通,应用到项目中,能够经过查看框架或者一些优秀开源项目获得启发性能

本文讲的是代理模式,由于要写关于AOP的随笔了,代理是跳不过去的,因此仍是单独写一下吧,方便本身理解、复习测试

代理模式

  生活中有不少代理的例子,不少职业都会有代理(微商、保险等),又或者是一个明星,他的经纪人也是代理,虽然这个代理有时很坑爹。this

。。又或者是Spring AOP,代理是一种思想,不仅是存在Javaspa

定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用

一、静态代理

SellCar.java为共同接口

public interface SellCar {
    void sellCar();
}

SellCarImpl.java目标对象

public class SellCarImpl implements SellCar{
    @Override
    public void sellCar() {
        System.out.println("selll car");
    }
}

SellCarProxy.java代理类

public class SellCarProxy implements SellCar{

    private SellCar sellCar;

    @Override
    public void sellCar() {
        System.out.println("sell car proxy start");
        if (null == sellCar) {
            sellCar = new SellCarImpl();
        }
        sellCar.sellCar();
        System.out.println("sell car proxy end");
    }
}

SellCarTest.java测试类

public class SellCarTest {

    public static void main(String[] args) {
        SellCar sellCar = new SellCarProxy();
        sellCar.sellCar();
    }
}

结果:

sell car proxy start
selll car
sell car proxy end

缺点:

  目标对象要建立好,做为代理类的内部属性。一个target对应一个proxy,这样若是须要代理的对象不少,难道就要写不少proxy吗?接口内

方法改了,target对象和proxy对象都要修改。若是咱们提早不知道目标对象是什么,这个都是静态代理存在的问题

二、动态代理

动态代理不关心target对象,而是在运行期间生成proxy

2.1).jdk动态代理

jdk自带的,不须要第三方jar包,使用简单但相对功能较弱

SellCarProxy.java

@AllArgsConstructor    //生成全参构造器
public class SellCarProxy implements InvocationHandler {

    private Object target;
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("sell car proxy start");
        Object o = method.invoke(target, args);
        System.out.println("sell car proxy end");
        return o;
    }
}

SellCarTest.java

public class SellCarTest {

    public static void main(String[] args) {
        SellCar sellCar = (SellCar) Proxy.newProxyInstance(
                SellCarImpl.class.getClassLoader(), SellCarImpl.class.getInterfaces(), new SellCarProxy(new SellCarImpl())
        );
        sellCar.sellCar();
    }
}

结果:

sell car proxy start
selll car
sell car proxy end

注意:

  第一/二个参数,必定是target类,而不是通用接口类,不然会报错:com.sun.proxy.$Proxy0 cannot be cast to com.it.SellCar,由于你

去获取接口的interface数组啊

  三个参数分别为:加载target的类加载器,target类实现的接口,实现对象

缺点:

  只能代理实现接口的类,若是没有接口,将没法使用

2.2).cglib动态代理

  CGLib采用了很是底层的字节码技术,整体性能比JDK自带的动态代理好,且功能十分强大其原理是经过字节码技术为一个类建立子类,并在子

类中采用方法拦截的技术拦截全部父类方法的调用,顺势织入横切逻辑。

首先须要引入jar包

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib-nodep</artifactId>
    <version>3.1</version>
</dependency>

SellCarProxy.java

public class SellCarProxy implements MethodInterceptor {

    private Object target;

    public Object getTarget(Object object) {
        this.target = object;
        Enhancer enhancer = new Enhancer();
        //设置父类,被代理类(这里是Car.class)
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this); // 回调方法
        return enhancer.create();   // 建立代理对象
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("sell car proxy start");
        methodProxy.invokeSuper(o, objects);    //代理类调用父类的方法
        System.out.println("sell car proxy end");
        return null;
    }
}

SellCarTest.java

public class SellCarTest {

    public static void main(String[] args) {
        SellCarProxy proxy = new SellCarProxy();
        SellCar sellCar = (SellCarImpl)proxy.getTarget(new SellCarImpl());
        sellCar.sellCar();
    }
}

结果:

sell car proxy start
selll car
sell car proxy end

2.3).ASM:这个不太懂,实现动态代理效率很高

静态代理和动态代理的区别:

  代理类的建立时间不一样,静态代理一般只能代理一个类,而动态代理能够代理多个,运行的时候才知道代理的是什么

  一、静态代理:是直接建立的代码,对其进行编译。代理类的class文件已经存在

  二、动态代理:程序运行过程,由反射机制动态生成

文章参考:公众号-方志朋-一块儿学设计模式 - 代理模式

相关文章
相关标签/搜索