Java中的代理技术

Java中的代理技术

 

以前发过一遍blog讲到了代理技术,发现理解有些错误,最近有又了些新的理解,总结一下

代理技术可以分为static proxy和dynamic proxy,两种代理技术用途也不同
static proxy 用的较少,因为每代理一个对象,都需要创建一个代理类,显然不是我们所期望的
dynamic proxy则用的比较广泛,因为不需要生成代理类,需要代理某个对象时,直接生成即可

 

下面主要讲一下dynamic proxy
说到代理,我们应该知道代理对象和被代理对象
首先写一个被代理对象的类,被代理的类需要实现一个接口,至于为什么非要实现接口,以前不明白,现在有些明白,自己揣摩的
不知道对不对


因为我们在搭框架的时候,有些时候并不知道咱们要代理什么,所以使用一个接口,当以后咱们需要代理某个类的对象时,只需要
让这个类实现这个接口就好了,这是我的理解
其次,JavaAPI其实提供了代理类,其底层实现的方法用到了接口,所以咱们还是弄一个接口吧...


interface Action {

 void sing();
 void dance(); 
}

public class Person {
 
 @Override
 public void sing() {
  System.out.println("singing...");
 }
 
 @Override
 public void dance() {
  System.out.println("dancing...");
 }
}


这样一个简单的被代理对象的生成类就写好了,经过上面的介绍,我们知道,动态代理是不需要创建代理类的,直接使用JavaAPI中
提供的Proxy代理类来获得代理对象


public class Demo {
 public static void main(String args[]) {


  //既然是代理,则先new出咱们需要被代理的对象
  final Action person = new Person();//这里是用final是因为下面的内部类中用到了此对象


  /*查看API中的Proxy代理类,发现有个方法newPrxoyInstance可以获得代理对象*/
  Object proxy = Proxy.newProxyInstance(args1, args2, args3);


  /*此方法有三个参数,一一介绍
   其实我们扩散思维一下,用动态代理技术无需创建代理类,那么咱们通过Proxy代理类的方法获得的代理对象
   如何跟被代理的对象产生关联呢?显然,跟方法中的参数有关系
      args1:这个参数是一个类加载器,哪个类的?还用说吗?当然是咱们被代理对象的那个类的加载器了,难道是阿猫阿狗的?
      args2:这个参数是一个接口的class对象,那个接口?当然是咱们被代理对象实现的那个接口的class对象了
      args3:这个参数就不好描述了,做的事情很多,咱们可以说前两个参数是让代理对象跟被代理对象产生关联,
      那么最后一个参数args3咱们可以理解为产生代理对象需要做些什么事情,这地方传入的是一个InvocationHandler接口类型的变量
      API上说的是:每个代理实例都具有一个关联的调用处理程序,我的理解是:这个第3个参数的机制就是帮我们解决如果用代理对象
      来调用被代理对象中的方法,因为既然是接口,那么肯定有一个抽象方法来帮助咱们关联"咱们需要调用的方法"
          arg3既然是接口类型的变量,则我们应传入一个实现该接口的类的对象,此处就是用匿名内部类,如下:
  */


  Object proxy = Proxy.newProxyInstance(person.getClass().getClassLoader(),
    person.getClass().getInterfaces(), new InvocationHandler() {
     
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) {


      /*这里又有三个参数,对于invoke方法,我们应该很熟悉,因为在反射中
      我们用到过,获得方法的对象method,然后调用,其中传入了2个参数,
      第一个参数是哪个对象调用此方法,第二个参数是调用该方法需传入的实参,
      那么我们可以猜想一下此处的invoke方法中的参数到底是些什么意思呢?
      我们调用某个类的一系列方法,现在不能直接调用,必须通过代理来访问,
      即通过代理对象(proxy)来访问方法,这个proxy就等同于被代理的类产生的对象,
      那根据反射中的method对象的invoke方法,我们不难猜出第一个参数就是调用那些
      方法的对象,这个对象应该是被代理的类产生的对象,但是现在我们用代理对象替换了
      被代理的对象,所以第一个参数就是代理的实例(其实调用这个invoke方法的对象就是代理的实例),
      第2个参数是1个Method对象,这个method就是真正反射的被代理的类中的方法的method对象了
      第3个参数是一系列参数,这些参数其实是我们调用的方法中传入的所有参数的数组
      */


      return Method.invoke(person, null);
      //此处也null是因为被代理类中的方法都是无参的,所以都可以默认为null,但如果有的方法无参,有的
      //方法有参数,那这个地方最好就写默认的args,也就是上面invoke方法中的第3个参数
     }
    });


  //现在咱们就产生了一个代理对象proxy,类型为Object,现在我们知道了要代理Person类,所以要强转
  //但是这里并不是强转成Person类,而是强转成接口类型
  
  //现在来调用被代理类中的方法
  ((Action)proxy).sing();
  ((Action)proxy).dance();
 }
}

这样,就实现了动态代理,写的有点乱,有些地方我貌似明白,但写的时候又出现了新的问题,以后在补充一些...

 

你可能感兴趣的:(java,api,object,null,Class,action)