JDK动态代理

代理模式

  代理模式是设计模式中非常重要的一种类型,代理模式从类型上来说,可以分为静态代理和动态代理两种类型。

静态代理

  1.定义一个共用的接口

 public interface UserService {
    void query();
 }

  2.目标类实现上述接口

public class UserServiceImpl implements UserService {
  public void query() {
      System.out.println("查询用户信息");
  }
}

  3.代理类实现代码增强

public class Proxy implements UserService{
    private UserService userService ;
    public Proxy(UserService  userService ){
        this.userService = userService ;
    }
    public void query() {
      System.out.println("开始查询");
      userService.query();
      System.out.println("结束查询");
   }
}

  4.通过调用代理类实现方法功能强化
缺点
  编译器就确定好代码,不能处理未知类型的数据啊,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐。因此,动态代理将静态代理在编译器的代码增强延缓到运行期实现。

动态代理

(1)Proxy 类提供了用于创建动态代理类和实例对象的方法,它是所创建的动态代理类的父类。
(2)InvocationHandler 接口是代理处理程序类的实现接口,每一个被生成的代理类实例都可以提供一个相关的代理处理程序类,代理类实例的方法被调用时会回调invoke()方法。

  1.定义共用接口

 public interface Cacu {
    int plus(int a,int b);
    int multiply(int a,int b);
 }

  2.目标类实现该接口

public class CacuImp implements Cacu {

  @Override
  public int plus(int a, int b) {
      return a+b;
  }

  @Override
  public int multiply(int a, int b) {
     return a*b;
  }
}

  3.创建动态代理类

public class ProxyTest {

   private static Object getProxy(final Object target) throws Exception{

    Class proxyClazz = Proxy.getProxyClass(target.getClass().getClassLoader(),target.getClass().getInterfaces());
    Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);

    /**
     * @param   proxy the proxy instance that the method was invoked on
     *                调用该方法的代理对象
     *
     * @param   method the {@code Method} instance corresponding to
     * the interface method invoked on the proxy instance.  The declaring
     * class of the {@code Method} object will be the interface that
     * the method was declared in, which may be a superinterface of the
     * proxy interface that the proxy class inherits the method through.
     *                在代理实例上调用的接口方法
     *
     * @param   args an array of objects containing the values of the
     * arguments passed in the method invocation on the proxy instance,
     * or {@code null} if interface method takes no arguments.
     *               在代理实例上的方法调用中传递的参数
     */
    Object proxy = constructor.newInstance(new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(method.getName() + "方法开始执行...");
            Object result = method.invoke(target,args);
            System.out.println(method.getName() + "方法执行结束...");
            return result;
        }
    });
    return proxy;
  }

  //精简版
   private static Object getProxy2(Object target) throws Exception {

    Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(method.getName() + "方法开始执行...");
            Object result = method.invoke(target,args);
            System.out.println(method.getName() + "方法执行结束...");
            return result;
        }
    });

    return proxy;
  }
  //测试
  public static void main(String[] args) throws Exception {
    Cacu target = new CacuImp();
    Cacu proxy = (Cacu) getProxy(target);
    proxy.plus(1,1);    //代理对象每次调用方法都会执行invoke里的方法
    proxy.multiply(2,2);
  }
}

类加载器
  1:JDK内部需要通过类加载作为缓存的key
  2:需要类加载器生成class
动态代理局限
  JDK动态代理只能代理接口。因为生成的代理类已经继承了Proxy类,Java是单继承的,所以没法再继承另外一个类了。

你可能感兴趣的:(JDK动态代理)