jdk动态代理

java动态代理机制中有两个重要的类和接口InvocationHandler(接口)和Proxy(类),这一个类Proxy和接口InvocationHandler是我们实现动态代理的核心;

实现jdk代理的几大步骤

1)通过实现InvocationHandler接口来自定义自己的InvocationHandler;

2)通过Proxy.getProxyClass获得动态代理类;

3)通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class);

4)通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入;

5)通过代理对象调用目标方法;

IHello接口

package com.lanhuigu.spring.proxy.jdk;
 
public interface People {
    void sayHello();
}

HelloImpl实现类

package com.lanhuigu.spring.proxy.jdk;
 
public class Teacher implements People {
    @Override
    public void sayHello() {
        System.out.println("Hello world!");
    }

MyInvocationHandler实现类(实现的是invocatinHandler接口)

说明每一个动态代理类的调用处理程序都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用

package com.lanhuigu.spring.proxy.jdk;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
public class MyInvocationHandler implements InvocationHandler {
 
    /** 目标对象 */
    private Object target;
 
    public MyInvocationHandler(Object target){
        this.target = target;
    }
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("------插入前置通知代码-------------");
        // 执行相应的目标方法
        Object rs = method.invoke(target,args);
        System.out.println("------插入后置处理代码-------------");
        return rs;
    }

   public static void main(String[] args)
           throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
       // 1、生成$Proxy0的class文件
       System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
       // 2、获取动态代理类
      //.Proxy类就是用来创建一个代理对象的类  
      //第一个参数表示获取Peopled的类加载器,第二个是真实类
       Class proxyClazz = Proxy.getProxyClass(People.class.getClassLoader(),People.class);
       // 3、获得代理类的构造函数,并传入参数类型InvocationHandler.class
       Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);
       // 4、通过构造函数来创建动态代理对象,将自定义的InvocationHandler实例传入  
      // constructor.newInstance后面有说明
       IHello iHello1 = (IHello) constructor.newInstance(new MyInvocationHandler(new Teacher()));
       // 5、利用对象来调用方法
       iHello1.sayHello();

第二种:   
People people = new Teacher();
      //代理对象的调用处理程序,我们将要代理的真实对象(people)传入代理对象的调用处理的构造函数中,
      //最终代理对象的调用处理程序会调用真实对象的方法
      InvocationHandler handler = new MyInvocationHandler(people);
/**		
* 通过Proxy类的newProxyInstance方法创建代理对象,我们来看下方法中的参数
     * 第一个参数:代理对象
 	  * 第二个参数:接口中的方法
     * 第三个参数:关联handler
        */
        People proxy = (People)Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);
        //System.out.println(proxy.toString());
        System.out.println(proxy.work());
    }

两种调用方法区别

Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数; 

Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。 

Class.newInstance() 抛出所有由被调用构造函数抛出的异常。 

Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的; 

Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值