jdk动态代理

1 jdk动态代理

1.1 什么是代理

代理模式是23种设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式。为了对外开放协议,B往往实现了一个接口,A也会去实现接口。但是B是“真正”实现类,A则比较“虚”,他借用了B的方法去实现接口的方法。A虽然是“伪军”,但它可以增强B,在调用B的方法前后都做些其他的事情。Spring AOP就是使用了动态代理完成了代码的动态“织入”。

解答2 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

1.2 使用代理的好处

使用代理好处还不止这些,一个工程如果依赖另一个工程给的接口,但是另一个工程的接口不稳定,经常变更协议,就可以使用一个代理,接口变更时,只需要修改代理,不需要一一修改业务代码。从这个意义上说,所有调外界的接口,我们都可以这么做,不让外界的代码对我们的代码有侵入,这叫防御式编程。代理其他的应用可能还有很多。
 

1.3代理的分类

上述例子中,类A写死持有B,就是B的静态代理。如果A代理的对象是不确定的,就是动态代理。动态代理目前有两种常见的实现,jdk动态代理和cglib动态代理。

1.4 什么是jdk动态代理

动态代理是在程序运行时通过反射机制操作字节码,从而动态的创建 字节码文件,进而创建代理对象。

1.5 jdk动态代理的实现

动态代理中有一些坑,比如说:

  1. JDK的动态代理要求被代理类必须实现接口,返回的代理对象也是该接口的实现类;如果想不实现接口,可以使用cglib
  2. 在实现InvocationHandler接口,重写incvoke()方法时,要注意method.invoke()的第一个参数要传被代理对象,不能传重写的invoke()方法的第一个参数,因为那个参数是代理对象。

jdk动态代理是代理的一种实现方式 只能代理接口

步骤

1 新建一个接口

2 新建一个实现类实现接口

3 新建一个代理类 实现java.lang.reflect.InvocationHandler接口

4 测试

1

package com.example;

public interface Subject {
  public void doSomeThing();
}

 2 

package com.example;

public class SubjectImpl implements Subject {

  @Override
  public void doSomeThing() {
    System.out.println("I do someThing");
  }


}

package com.example;

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

/*
jdk动态代理
 */
public class JDKDynamicProxy implements InvocationHandler {

  private Object target;

  public JDKDynamicProxy(Object target) {
    this.target = target;
  }


  /*
    获取被代理接口实例对象
     */
  public <T> T getProxy(){
    return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);

  }


  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("do somethig before");
    Object result = method.invoke(target,args);
    System.out.println("dosomething after");
    return result;
  }


}

package com.example;

public class TestJdkProxy {

  public static void main(String[] args) {
    // 保存生成的代理类的字节码文件
    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

    Subject subject = new JDKDynamicProxy(new SubjectImpl()).getProxy();

    subject.doSomeThing();
  }


}

 

5 测试结果

do somethig before
I do someThing
dosomething after

2 jdk动态代理的原理

涉及的主要类

com.lang.reflect.Proxy

com.lang.reflect.InvocationHandler

java.lang.reflect.WeakCache
sun.misc.ProxyGenerator

JDK代理是不需要第三方库支持,只需要JDK环境就可以进行代理,使用条件:

1)实现InvocationHandler 

2)使用Proxy.newProxyInstance产生代理对象

3)被代理的对象必须要实现接口

2 cglib动态代理

区别:jdk动态代理利用拦截器InvocationHandler 加上反射机制生成一个匿名代理类 在调用具体方法之前调用InvokeHandler处理

Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值