静态代理 和 动态代理

一 概述

通过代理对象访问目标对象,在原有类的行为基础上,加入一些多出的行为,甚至完全替换原有而行为,

静态代理:

代理类必须要有一个被代理对象的引用,静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。对于我们不关心的方法,全部委托给被代理的对象的引用,自己处理关心的方法。这种代理是死的,不会在运行时动态创建,而且静态代理的对象很固定。

图形描述和静态代理模式类图如下

  

/**
 * 目标对象实现的接口
 * @author jiyukai
 */
public interface BussinessInterface {
 
    void execute();
}
 
/**
 * 目标对象实现类
 * @author jiyukai
 */
public class Bussiness implements BussinessInterface{
 
    @Override
    public void execute() {
        System.out.println("执行业务逻辑...");
    }
}
 
/**
 * 代理类,通过实现与目标对象相同的接口
 * 并维护一个代理对象,通过构造器传入实际目标对象并赋值
 * 执行代理对象实现的接口方法,实现对目标对象实现的干预
 * @author jiyukai
 */
public class BussinessProxy implements BussinessInterface{
     
    private BussinessInterface bussinessImpl;
     
    public BussinessProxy(BussinessInterface bussinessImpl) {
        this.bussinessImpl = bussinessImpl;
    }
     
    @Override
    public void execute() {
        System.out.println("前拦截...");
        bussinessImpl.execute();
        System.out.println("后拦截...");
    }
}

静态代理的总结

  优点:可以做到不对目标对象进行修改的前提下,对目标对象进行功能的扩展和拦截。

  缺点:因为代理对象,需要实现与目标对象一样的接口,会导致代理类十分繁多,不易维护,同时一旦接口增加方法,则目标对象和代理类都需要维护。

动态代理:

  • 运行期间生成动态代理类
  • 代理类需要去实现一个接口:InvocationHandler,实现invoke方法
  • 调用Proxy.newProxyInstance(classLoader,interfaces,代理类实例)构造代理对象
  • 生成的代理对象调用方法
  • 目的:解耦合 

一个JDK动态代理的例子

动态代理的类图(只是方便本人理解,与下面的代码不对应)

標題

 

public interface ISomeService {
  String doFirst();
  void doSecond();
  String doThird();
}
//目标类:代理类要增强的类
public class SomeServiceImpl implements ISomeService {
  @Override
  public String doFirst() {
    return "AAAbbb";
  }
  @Override
  public void doSecond() {
    System.out.println("SomeServiceImpl:执行doSecond()");
  }
  @Override
  public String doThird() {
    return "aaa";
  }
}
public class Mytest {
  public static void main(String[] args) {
    ISomeService target = new SomeServiceImpl();
    ISomeService someService = (ISomeService) Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        new InvocationHandler() {
          // proxy:代理对象
          // method:目标方法
          // args:目标方法的参数列表
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = method.invoke(target, args);
            if(result!=null) {
              result=((String)result).toUpperCase();
            }
            return result;
          }
        });
    System.out.println(someService.doFirst());
    someService.doSecond();
    System.out.println(someService.doThird());
  }
}

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

  1. 静态代理在程序运行以前,代理类就应存在了。动态代理类在程序运行时,运行反射机制动态创建而成。
  2. 静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
  3. 静态代理事先知道要代理的是什么,动态代理只有在运行时才知道。

使用场景

  • 需要修改或者屏蔽一个类或者若干个类的部分方法,复用其他方法,可选择静态代理。
  • 若是要拦截一批类中的某些方法,在方法执行前后做一些操作,若这些类有接口,则选择动态代理,否则使用cglib。

猜你喜欢

转载自blog.csdn.net/qfc8930858/article/details/89715972