javaSE动态代理

简单创建动态代理的步骤:
1.创建一个实现类(动态代理类)实现接口InvocationHandler,并且他必须实现invoke方法。
2.创建被代理的类以及接口。
3.通过Proxy的静态方法
Proxy.newProxyInstance(ClassLoader loader, Class[]interfaces, InvocationHandler handler)创建一个代理。
此方法返回一个对象,需要将返回对象转换为被代理类的接口。
4.通过代理调用方法。
 
 
下面是创建一个完整动态代理类过程:
1.创建Subject接口里面方法为无参的request方法 创建真正的RealSubject类并实现request方法,再次省略以上描述代码。
 
2.创建一个动态代理类并实现InvocationHandler比实现起方法。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 实现动态代理必须要实现IvocationHandler接口 * * 调用subject对象的方法并传递的是args参数,由于实际代理的类RealSubject的request方法里面没有参数,故而args为空 * 如果有参数,系统将会生成一个Object类型的数组,来代表request方法里的参数 * method.invoke(subject, args)实际就是调用被代理类的将要执行的方法。 * @author Jeelon * */ public class DynamicProxySubject implements InvocationHandler { private Object subject; public DynamicProxySubject(Object object){ this.subject = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before calling :" + method); method.invoke(subject, args); System.out.println("after calling :" + method); return null; } }
 
 
 
3.客户端生成动态代理并获得动态生成的类 且调用其方法
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client {
	public static void main(String[] args) {
		
		RealSubject realSubject = new RealSubject();
		InvocationHandler dynamicProxySubject = new DynamicProxySubject(realSubject);
		
		//下面的代码一次性生成代理
		Class<?> classType = dynamicProxySubject.getClass();
		Subject subject = (Subject)Proxy.newProxyInstance(classType.getClassLoader(), realSubject.getClass						().getInterfaces(), dynamicProxySubject);
		
		//调用Subject的方法
		subject.request();
	}
}
 
 
 
第二个例子:在一个类中完成(代理Vector)
 
public class VectorProxy implements InvocationHandler {
	private Object proxyObject;

	public VectorProxy(Object object) {
		this.proxyObject = object;
	}

	public static Object factory(Object obj) {

		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
				obj.getClass().getInterfaces(), new VectorProxy(obj));
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {

		System.out.println("before calling:" + method);

		Object object = method.invoke(proxyObject, args);

		if (null != args) {
			for (Object obj : args) {
				System.out.println(obj);
			}
		}
		System.out.println("after calling:" + method);

		return object;
	}

	public static void main(String[] args) {
		@SuppressWarnings("unchecked")
		List<String> vector = (List<String>) factory(new Vector<String>());
		vector.add("Jeelon");
		vector.add("Merry");
		vector.add("Jerry");
		
		System.out.println(vector);
		
		vector.remove(0);
	}
}

解析:

1. Proxy即动态代理类;

2. Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用;

它有三个参数:

ClassLoader loader ----指定被代理对象的类加载器

Class[] Interfaces ----指定被代理对象所以事项的接口

InvocationHandler h ----指定需要调用的InvocationHandler对象

3. 实现InVocationHandler接口的LogHandler_old对象

这个对象的invoke()方法就是Proxy这个动态代理类所代理的接口类的抽象方法的真实实现;

它有三个参数:

Object proxy -----代理类对象

Method method -----被代理对象的方法(这里不是接口的抽象方法了,是具体的实现类中的方法)

Object[] args -----该方法的参数数组

JDK中具体的动态代理类是怎么产生的呢?

1.产生代理类$Proxy0类

执行了Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

将产生$Proxy0类,它继承Proxy对象,并根据第二个参数,实现了被代理类的所有接口,自然就可以生成接口要实现的所有方法了(这时候会重写hashcode,toString和equals三个方法),但是还没有具体的实现体;

2. 将代理类$Proxy0类加载到JVM中

这时候是根据Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第一个参数----就是被代理类的类加载器,把当前的代理类加载到JVM中

3. 创建代理类$Proxy0类的对象

调用的$Proxy0类的$Proxy0(InvocationHandler)构造函数,生成$Proxy0类的对象

参数就是Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第三个参数

这个参数就是我们自己实现的InvocationHandler对象,我们知道InvocationHandler对象中组合加入了代理类代理的接口类的实现类;所以,$Proxy0对象调用所有要实现的接口的方法,都会调用InvocationHandler对象的invoke()方法实现;

4. 生成代理类的class byte

动态代理生成的都是二进制class字节码




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值