黑马程序员---java动态代理



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

动态代理概述

对于动态代理简单的理解:动态代理分为两部分,一是代理,二是动态。

什么是代理?类似于现实生活中的代理商,就是可以帮你办特定事情的机构。比如各大产品的代理商。

java中的动态代理是指。程序在运行时,动态的为你生成一个类似于生活中的代理商,

当生成这个代理商之后,你要调用某些功能就不用再找目标类了,

只要找到这个动态生成的代理类,将自己的需求告诉代理,代理再将请求转达给目标类,

然后完成某些需要(也就是说有了代理商之后,你买产品不用再直接找厂家了,找到代理商就可以买)。


程序在运行时创建指定接口的一个代理类 ,通过代理类

与目标类通过反射进行关联。我们在开发的过程中,要完成某些功能时

已有的方法不能完成当前的需求,需要对某些类的方法进行增强。方法

增强的办法有许多种,比如继承和包装(即装饰设计模式),还有动态代理等等。

代理类的架构图如下:

AOP是指面向方面的编程(Aspect Oriented Program,简称AOP

实际开发中,系统中往往存在一些交叉业务,

比如安全,日志和事务等等功能要贯穿到好多个模块当中,这些就叫交叉业务。一个交叉业务又需要切人到系统中的一个方面,

这时候可以使用aop将这些交叉业务模块化。可以曹勇将切面代码移动到原始方法的周围,

这与直接在方法中编写切面代码的运行效果一样。而动态代理正好可以完成这一功能。代理实现了AOP功能的核心和关键。

要为系统中的各种接口的类增加代理功能的代理类,需要编写大量的代理类。

JVM可以在运行时动态生成类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。

这样就不需要我们手动的为每一个类都增加代理类。但JVM在生成动态类时必须实现一个或者多个接口。

所以,JVM生成的动态类只能用作具有形同接口的目标类的代理。也就是说,当类没有实现任何接口的时候,

JVM是不能生成代理类的。为了解决这个问题,可以使用CGLIB库,它可以动态的生成一个类的子类,

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

Proxy类:

Proxy类是实现动态代理的核心类。

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

动态代理类是一个实现在创建类时在运行时指定的接口列表的类。代理接口是代理类实现的一个。

代理实例是代理类的一个实例。每个代理实例都有一个关联的调用处理程序的对象,它可以实现InvocationHandler

通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的Invoke方法,并传递代理实例,

识别调用方法的java.lang.reflect.Method对象以及包含参数的Object类型的数组。带哦用处理程序以适当的方式处理编码的方法调用,

并且它返回的结果将作为代理实例上方法调用的结果返回。

Proxy类具备以下属性

1.代理类是公共的,最终的,而不是抽象的。

2.未指定代理类的非限定名称。但是,以字符串$Proxy开头的类名空间应该为代理类保留。

3.代理类扩展java.lang.reflect.Proxy

4.代理类会按同一顺序准确地实现其创建时指定的接口。

5.如果代理类实现了非公共接口,那么它将在与该接口相同的包中定义。否则,代理类的包也是未指定的。

注意,包密封将不阻止代理类在运行时在特定包中的成功定义,也不会阻止相同类加载器和带有特定签名的包所定义的类。

6.由于代理类将实现所有在其创建时指定的接口,所以对其 Class 对象调用 getInterfaces 将返回一个

包含相同接口列表的数组(按其创建时指定的顺序),对其 Class 对象调用 getMethods 将返回一个

包括这些接口中所有方法的 Method 对象的数组,并且调用 getMethod 将会在代理接口中找到期望的一些方法。

7.每个代理类都有一个可以带一个参数(接口 InvacationHandler的实现)的公共构造方法,

用于设置代理实例的调用处理程序。并非必须使用反射 API 才能访问公共构造方法,

通过调用Proxy.newInstance方法(将调用Proxy.getProxyClass的操作和调用带有

调用处理程序的构造方法结合在一起)也可以创建代理实例。


动态代理工作原理图:


下面是通过创建Collection的代理来操作目标类ArrayList的程序代码

package com.itheima;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

public class ProxyTest
{

	/**
	 * @param args
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException
	{
             //获取代理类字节码
             Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), 
				Collection.class);
		System.out.println(clazzProxy1);
		//获取构造方法
		Constructor[] constructors = clazzProxy1.getConstructors();
		//按自定义格式打印构造方法
		for (Constructor constructor : constructors)
		{
			String name = constructor.getName();
			
			StringBuilder sb = new StringBuilder(name);
			sb.append("(");
			Object[] types = constructor.getParameterTypes();
			
			for (int i = 0; i < types.length; i++)
			{
				sb.append(types[i]);
				
				if (i!=types.length-1)
				{
					sb.append(",");
				}
			}
			sb.append(")");
			System.out.println(sb);
			System.out.println();
		}
		//获取方法
		Method[] methods = clazzProxy1.getDeclaredMethods();
		
		for (Method method : methods)
		{
			String name = method.getName();
			
			StringBuilder sb = new StringBuilder(name);
			sb.append("(");
			Object[] types = method.getParameterTypes();
			
			for (int i = 0; i < types.length; i++)
			{
				sb.append(types[i]);
				
				if (i!=types.length-1)
				{
					sb.append(",");
				}
			}
			sb.append(")");
			System.out.println(sb);
			System.out.println();
		}
		//通过构造方法构建代理类实例对象
		Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
		Collection proxy1 = (Collection) constructor.newInstance(new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable
			{
				// TODO Auto-generated method stub
				return null;
			}});
		System.out.println(proxy1);
		//动态生成代理类字节码的同时构建它的实例对象。
		Collection proxy3 = (Collection)Proxy.newProxyInstance(
				Collection.class.getClassLoader(), 
				new Class[]{Collection.class}, 
				new InvocationHandler(){
					ArrayList target = new ArrayList();
					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable
					{
						// TODO Auto-generated method stub
						 
						return method.invoke(target, args);
					}});
		System.out.println(proxy3.getClass()+"   .....");
		System.out.println(Proxy.isProxyClass(clazzProxy1));
		//通过代理操作	
		proxy3.add(345);
		proxy3.add("Tomorrow is a nother day.");
		proxy3.add(new Date());
		proxy3.add('我');
		Iterator it = proxy3.iterator();
		
		while (it.hasNext())
		{
			System.out.println(it.next());
		}
	}

}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值