代理模式

代理模式

    • 1.什么是代理模式
    • 2.代理模式的使用场景
    • 3.代理模式的实现
      • 3.1 静态代理
      • 3.2 JDK动态代理
      • 2.3 cglib动态代理
    • 4.总结

1.什么是代理模式

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。这样做的好处是: 在不修改目标对象源码的基础上,通过代理可以实现对目标对象进行扩展。

简单来说

  • 就是我们通过在某个接口(Interface)的实现类(preClass)的基础上,新建一个代理对象(proxyClass)来实现该接口。
  • 该代理对象中调用了preClass的方法,并且在调用方法的前后新增了一些功能。
  • 这样我们供外部调用的preClass的时候,我们直接调用代理对象proxyClass,这样不仅实现了preClass的功能,还在它的基础上新增了一些功能。

2.代理模式的使用场景

(1)当我们想要隐藏某个类时,可以为其提供代理类

(2)当一个类需要对不同的调用者提供不同的调用权限时,可以使用代理类来实现(代理类不一定只有一个,我们可以建立多个代理类来实现,也可以在一个代理类中金进行权限判断来进行不同权限的功能调用)

(3)当我们要扩展某个类的某个功能时,可以使用代理模式,在代理类中进行简单扩展(只针对简单扩展,可在引用委托类的语句之前与之后进行)

3.代理模式的实现

3.1 静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继承相同的父类。

静态代理优缺点:

①可以做到在不修改目标对象功能的情况下,对目标对象进行功能扩展

②因为代理对象需要与目标对象实现相同的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都需要维护.

3.2 JDK动态代理

①代理对象不需要实现接口

②代理对象的生成,是利用JDK的api,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)

③动态代理也叫:JDK代理,接口代理

JDK动态代理实现代理工厂类:MyInvocationHandler

class MyInvocationHandler implements InvocationHandler{
    Object obj;//实现了接口的被代理类的对象的声明
    //作用:①给被代理类的对象实例化 ②返回一个代理类的对象
    public Object blind(Object obj){
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }
    //当通过代理类的对象发起对被重写的方法调用时,都会转化为对如下invoke方法的调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method方法的返回值
        Object returnVal = method.invoke(obj, args);
        return returnVal;
    }
}
public class TestProxy {
    public static void main(String[] args) {
        //1.被代理类的对象
        RealSubject real = new RealSubject();
        //2.创建一个实现了InvocationHandler接口的类的对象
        MyInvocationHandler handler = new MyInvocationHandler();
        //3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类对象
        Object obj = handler.blind(real);
        Subject sub = (Subject)obj;//此时sub就是代理类对象
        sub.action();//转到对InvacationHandler接口的实现类的invoke()方法的调用

    }
}

JDK动态代理:

  • 代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
  • jdk动态代理的代理对象在创建时Proxy.newProxyInstance(),需要传入参数(被代理对象,被代理对象的接口)

2.3 cglib动态代理

cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理.

定义一个被代理的类:

class Book{
    public void addBook(){
        System.out.println("新增书籍");
    }
}

cglib生存一个动态代理类:

class BookCGlib implements MethodInterceptor{
    private Object target;//业务类对象,供代理方法中进行真正的业务方法调用

    //相当于jdk动态代理中的绑定
    public Object getInstance(Object target){
        this.target = target;//给业务方法赋值
        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer();
        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(this.target.getClass());
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而CallBack则需要实现intercept()方法进行拦截
        enhancer.setCallback(this);
        return enhancer.create();
    }

    //实现回调方法
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        System.out.println("-----预处理-------");
        proxy.invokeSuper(obj, args);//调用业务类(父类中的方法)
        System.out.println("-----调用后操作-----");
        return null;
    }

} 

cglib动态代理:

  • 被代理的对象不需要实现某个接口,代理对象通过继承被代理对象,重写父类的方法来实现动态代理的。
  • 代理对象需要传入一个参数(被代理对象的实例)

4.总结

①静态代理是通过在代码中显式定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装.用户通过代理类调用包装过的业务方法;

②jdk动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法

③CGlib动态代理是通过继承被代理类,生成的动态代理类是被代理类的子类,通过重写被代理类方法进行代理

你可能感兴趣的:(Java设计模式)