动态代理


---------------------------------------------------------------------------------------
代理:
安全,事务,日志
静态代理:
自己需要写,成百上千个代理类.
动态代理:
可以对实现接口的任意类的接口中的方法的外层,包上任意的处理逻辑.
----------------------------------------------------------------------------------------
目标类,动态类,代理类:
1.目标类,就是被代理的类,
2.动态类,就是动态生成的类,可以有多种实现方式,
3.代理类,一般就是动态生成的,所以也叫动态代理类,
动态类的种类:
1.JVM生成的动态类,要求必须实现接口,可以用作具有相同接口的类的,代理类.
2.CGLIB库生成的动态类,可以生成目标类的一个子类,这个子类也可以用作目标类的,代理类.
动态代理类的种类:
1.JVM生成的动态代理类,要求目标类和代理类,都实现相同的接口.
2.CGLIB库生成的动态代理类,通过动态生成目标类的一个子类,来代理目标类,不需要实现接口.
生成的动态代理类中的方法,可以有的内容:
1.调用目标类中的相应方法并返回值,
2.在调用目标类中的相应方法之前,之后,前后,加上代理类自己的处理逻辑,
3.在调用目标类中的相应方法的异常的,catch语句块中,也可以加上代理类自己的处理逻辑.
----------------------------------------------------------------------------------------
查阅Java SE 6-API:
java.lang.reflect.Proxy类中的方法:
protected Proxy(InvocationHandler h)
构造方法,接收一个接口类型的参数,
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces) throws IllegalArgumentException
在内存中,搞出这个动态代理类的字节码,
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
直接一步到位,既搞出了这个动态代理类的字节码,又搞出了这个字节码的实例对象,
public static boolean isProxyClass(Class<?> cl)
是否是一个Proxy类或Proxy类的子类,
public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException

InvocationHandler接口中的方法:
这个接口的作用,就是告诉代理类,如何代理一个目标类,接口中只有一个方法:
Object invoke(Object proxy,Method method,Object[] args) throws Throwable
1.InvocationHandler接口中的invoke方法,与Method类中的invoke方法完全不是一回事,参数也不一样.
2.InvocationHandler接口中的invoke方法,更像是Runnable接口中的run方法,可以实现数据共享!
------------------------------------------------------------------------------------------
JVM生成的动态代理类的特点:
1.运行时动态生成的动态代理类的字节码,是Proxy类的一个子类,
System.out.println(clazzProxy1 == Proxy.class);  //结果:false
System.out.println(Proxy.isProxyClass(clazzProxy1));  //结果:true
2.生成的这个动态代理类,只有一个构造方法,构造方法中的参数与Proxy类相同,
Constructor[] constructors = clazzProxy1.getConstructors();
for(Constructor constructor:constructors)
{
 System.out.println(constructor);
}
 //结果:public $Proxy0(java.lang.reflect.InvocationHandler)
Proxy类:protected Proxy(InvocationHandler h)
3.发现接口中没有返回值的方法,可以成功调用,有返回值的方法,抛NullPointerException.
JVM生成的动态代理类中方法有:
1.实现了接口中的所有的方法,不过都改成是final的,(并交给handler处理器),
2.重写了Object类中的hashCode,equals,toString方法,也都改成是final的,(并交给handler处理器),
3.继承了Proxy类中的4个可见的方法,(并不交给handler处理器)
注意:
1.除了重写Object类中的以上3个方法,其它的从Object继承而来的方法,不再重写了,
2.以上内容,可以从Java API-Proxy类,中得到说明.
案例:
实例化这个动态生成的代理类,
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
Proxy obj = (Proxy) constructor.newInstance(new InvocationHandler()
{
 //可以把共享的目标类的对象,放在这里,
 @Override
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable
 {
  //这个位置,才是代理类的主要逻辑的,实现现场.
  return null;
  //return method.invoke(proxy,args);      这是一个死循环!
 //由此可见,
 //动态代理设计模式,整个过程中,并没有使用迭代的方法,
 //动态代理设计模式,只是一个简单的参数传递的过程,
 //动态代理设计模式,内部所传递的内容,就是一个Method对象和实参列表.
 }
});
System.out.println(obj);   //返回值为null
JVM中的动态代理类,与InvocationHandler对象,的关系:
1.动态代理类,调用目标类的方法,是通过反射的方式,
2.反射所需要的Method对象,是通过实现接口,来创建的,
3.反射所需要的目标对象,是通过外界调用代理类的方法,传递过来的,
原理:
代理类所实现的接口中的每一个方法,实际上都调用了同一个InvocationHandler对象的invoke方法,
----------------------------------------------------------------------------------------
实例分析,动态代理类,内部运行原理:
class $Proxy0 implements Collection
{
 InvocationHandler handler;
 public $Proxy0(java.lang.reflect.InvocationHandler handler)
 {
  this.handler = handler;
 }
 int size()              //实现了接口中的方法
 {
 return handler.invoke(this,this.getClass().getMethod("size"),null);
 }
 add(Object object)      //实现了接口中的方法
 {
 return handler.invoke(this,this.getClass().getMethod("add",Object[]{object});
 }
 ...
}
技巧:
把目标类的对象,写在InvocationHandler类中,并写在invoke方法的外面,可以实现数据共享!
---------------------------------------------------------------------------------------
面向切面的编程:
向InvocationHandler对象中传入更多的东西,IOC-控制反转,
1.传入被代理的目标类的对象,
2.传入带有处理逻辑的对象,
案例:
对动态代理,继续进行抽取和重构.
 
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值