黑马程序员———动态类

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



程序中的代理:
要为已有的 多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理,日志,计算方法的时间,事务管理,等待。

--------------------

代理架构图:

Client 客户端调用程序      接口  doSomeThing()
  |      |
  |      |
  ↓      ↓
   
Proxy  代理类     Target   目标类
doSomething(){        doSomeThing(){
//前置功能代码   //业务功能代码
目标对象:doSomeThing()  }
//后置功能代码
}

--------------------------


系统中存在交叉业务,一个业务就是要切入到系统的一个方面,
  安全 事务 日志
StudentService---|---|-----|------------
CourseService ---|---|-----|------------
Miscservice   ---|---|-----|------------

具体代码描述交叉业务:
method1         method2        method3
{  {  {
---------------------------------------切面

....            .....           .....

----------------------------------------切面
}  }  }

交叉业务的编程问题即为面向方面的编程(Aspect oriented program)),AOP
的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围。
这与直接在方法中编写切面代码的效果是一样的。
------------------------------------切面
func1  func2  func3
{  {  {
...  ...  ...
 }  }    }
----------------------------------切面


重要原则:不要把供货商暴露给你的客户!!!!

使用代理技术正好可以解决这种问题,代理是实现AOP功能的
核心和关键技术。


=======================================================

动态代理技术

为系统中的各种接口增加代理功能,需要很多代理类,全部采用静态代理方式,
很麻烦。JVM可以在运行时期生成出类的字节码,这种动态生成的类
往往被用作代理类,既动态代理类。

JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类
只能用作具有相同接口的目标类的代理。

CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的
代理,所以,如果要为一个没有实现接口的类生成动态代理类,
那么使用CHLIB库。

代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以
在代理方法中的如下四个位置加上系统功能代码:
1.在调用方法之前
2.在调用方法之后
3.在调用方法前后
4.在处理目标方法的catch块中

 

=======================================================

分析JVM动态生成的类


创建实现了Collection接口的动态类和查看其名称,分析Proxy.getProxyClass方法的各个参数。
编码列出动态类中的所有构造方法和参数签名。
编码别处动态类中的所有方法和参数签名。
创建动态类的实例对象
 用反射获取构造方法
 编写一个最简单的InvocationHander类
 调用构造方法创建动态类的实例对象,并将编写得InvocationHander实例对象传进去。
 打印创建的对象和调用对象的没有返回值的方法和getClass方法,演示调用其他有
 返回值的方法并报告了异常。

总结:让JVM创建动态类,需要给它提供哪些信息?
三个方面:
 生成的类中有哪些方法,通过让其实现哪些接口的方法进行告知。
 产生的字节码必须有一个关联的类加载器对象
 生成的类的方法的代码是怎么样的呢?也得由我们提供,把我们写的代码写在一个
 约定好了接口对象的方法中,把对象传给它,它调用我们的方法,既相当于
 插入我的代码。提供执行代码的对象就是那个InvocationHander对象,它是在创建
 动态类的实例对象的构造方法时传递进去的。在上面的InvocationHander对象的invoke
 方法中加一点代码,就可以看到这些代码被调用运行了。
用Proxy.newProxyInstance方法直接一步就创建出代理对象。
 

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

创建某一接口 Foo 的代理:

     InvocationHandler handler = new MyInvocationHandler(...);
     Class proxyClass = Proxy.getProxyClass(
         Foo.class.getClassLoader(), new Class[] { Foo.class });
     Foo f = (Foo) proxyClass.
         getConstructor(new Class[] { InvocationHandler.class }).
         newInstance(new Object[] { handler });

 或使用以下更简单的方法:
     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                          new Class[] { Foo.class },
                                          handler);
 

态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,
该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。
代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象,
它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将
被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的
java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以
适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。


每个代理实例都有一个关联的调用处理程序,它会被传递到其构造方法中。
静态 Proxy.getInvocationHandler 方法将返回与作为其参数传递的代理实例相关
的调用处理程序。
代理实例上的接口方法调用将按照该方法的文档描述进行编码,并被指派到调用处理程序的
 Invoke 方法。

static InvocationHandler getInvocationHandler(Object proxy)
          返回指定代理实例的调用处理程序。
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
          返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。
static boolean isProxyClass(Class<?> cl)
          当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
          返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

 

 -----------------------------------
InvocationHandler 是代理实例的调用处理程序 实现的接口。

每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,
将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
 Object invoke(Object proxy, Method method, Object[] args)
          在代理实例上处理方法调用并返回结果。
 

 

<span style="font-size:18px;">------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------</span>


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值