64.黑马程序员-代理

来源:互联网 发布:js click target 编辑:程序博客网 时间:2024/04/30 09:26

------- android培训、java培训、期待与您交流! ----------

一、代理的概念
  •  生活中的代理
    • 武汉人从武汉的代理商手中买联想电脑和直接跑到北京传智播客旁边来找联想总部买电脑,你觉得最终的主体业务目标有什么区别吗?基本上一样吧,都解决了核心问题,但是,一点区别都没有吗?从代理商那里买真的一点好处都没有吗?
  • 程序中的代理
    • 要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法的运行时间、事务管理、等等,你准备如何做?
    • 编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。 (参看下页的原理图)
    • 如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易
二、AOP()
    系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面,如下所示:
                              安全       事务         日志
StudentService  ------|----------|------------|-------------
CourseService   ------|----------|------------|-------------
MiscService       ------|----------|------------|-------------
用具体的程序代码描述交叉业务:
method1         method2          method3
{                      {                       { 
------------------------------------------------------切面
....            ....              ......
------------------------------------------------------切面
}                       }                       }
交叉业务的编程问题即为面向方面的编程(Aspect oriented program ,简称AOP),AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的,如下所示:
------------------------------------------------------切面
func1         func2            func3
{             {                { 
....            ....              ......
}             }                }
------------------------------------------------------切面
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
  • AOP(面向方面的编程)
    • 要做的事情是把交叉业务模块化,只写一份,其他的地方都能应用上。
    • 我们不可能改变目标的方法、深入到方法内部去修改,只能通过代理。
    • 但是我们可以让用户感觉到我们修改了方法,比如在方法周围加上代码。
  • 怎样解决AOP问题?
    • 代理技术可以解决这个问题。
  • 动态代理技术
    • 要为各种接口的类加上代理功能,那需要太多的代理类,全部采用静态代理,非常麻烦。动态代理可以解决这个问题。
    • 原理:
      • 1.JVM可以动态的生成类(字节码)。这个方法调用N遍,就生成N个类。
      • 2.动态生成的类不是代理类,但是往往被用作代理类(即动态代理类)。
      • 注意:JVM生成的动态类必须实现一个或多个接口,这样生成的类就有了方法。
      • 注意:如果目标类没有实现接口,JVM生成的动态类无法用作它的代理类。要想能代理的方法之一是:使用CGLIB库, CGLIB可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,因为拥有该类的相同的方法。
      •  位置:在调用方法前、后、前后、处理异常的catch块内部,四个位置。
三、JVM动态生成的类
  • JVM动态生成的类, 本身不是 代理类, 但 可以用作代理类。

    • 1,一定要给它( JVM动态生成的类 )一个接口。
    • 2,staticClass<?>getProxyClass(ClassLoader loader, Class<?>... interfaces) 
                返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。


  • 总结:让JVM创建动态类及其实例对象,需要给它提供哪些信息?
    • 三个方面:
      • 生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知;
      • 产生的类字节码必须有一个关联的类加载器对象;
      • 生成的类中的方法的代码是怎样的,也得由我们提供。把我们的代码写在一个约定好了接口对象的方法中,把对象传给它,它调用我的方法,即相当于插入了我的代码,提供执行代码的对象就是那个invocationHandle对象,它是在创建动态类的实例对象的构造方法时传递进去的。在上面的invacationHandle对象的invoke方法中加一点代码,就可以看到那些代码被调用运行了。
  • 总结:让创建动态类和创建其实例对象合起来,一步到位的办法。
    • Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),                                          new Class[] { Foo.class },                                          handler);
      staticObjectnewProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)            返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
  • a
  • 动态类的内部代码分析
    • 动态生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口的所有方法和一个如下接受invocationHandler参数的构造方法。
    • 构造方法接收一个invocationHandler对象,接收对象要干什么用?该方法内部的代码会是怎么样的?
      • 接受这个参数,是为了把这个对象(参数) 提供给 自己内部成员变量使用。代码是this.handler=handler;
      • 那么什么时候用这个对象?
    • 实现的Collection接口中的各种方法的代码又是怎么样的呢?invocationHandler接口中定义的invoke方法的三个参数优势什么意思?图解说明:
      • 我们使用代理类的方法,如proxy3.add(),代理的add方法内部去找通过参数获得的invocationHandler对象,然后调用这个对象的invoke()方法。所以我们每调用一次add(),就执行了一次invoke()方法。







原创粉丝点击