java动态代理

1. 动态代理是什么?

    代理:A需要访问C,但是A又不能或不想直接访问C,如果说A可以通过B来访问C,此时B就是C的代理。在java中,B需要实现和C一样的接口,这样B才能代理C完成任务,实际的任务的完成还是有C来完成。

    静态代理:在编译时,代理类的.class文件就已经存在。

    动态代理:在运行时,动态生成代理类。很显然动态代理的实现需要用到java的反射机制。

2.为什么要使用动态代理?

    相对于不使用代理的情况,使用代理可以在调用被代理类的方法时,添加其他操作,比如过滤消息、对消息预处理以及消息处理之后等操作。

    相对于静态代理来说,静态代理在编译时,被代理类就必须存在,且每个代理对象中都会包含一个被代理对象,这样会导致类急剧膨胀。

3. 如何使用动态代理

    动态代理的实现主要依赖于Proxy类和InvocationHandler接口。

    Proxy类中的Static Object newProxyInstance(ClassLoader loader, Class[] intefaces, InvocationHandler h)函数会做:1.根据interfaces动态生成代理类proxy.$Proxy0 2.生成一个proxy.$Proxy0的对象并返回给调用者 3.调用者调用proxy.$Proxy0中的方法时,最终会通过调用h中的invoke()函数来调用被代理类的方法。

    InvocationHandler接口通常会被代理类继承,接口实例会被传入到newProxyInstance()方法,动态代理类的对象最终会通过InvocationHandler中的invoke()函数来调用被代理的对象,使用的是java反射机制。

Subject.java:

package com.zhb.dynamicproxy;

public interface Subject {
	void request();
}

AnotherSubject.java:

package com.zhb.dynamicproxy;

public interface AnotherSubject {
	public String Hello(String a);
}

DynamicSubject.java:

package com.zhb.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//需要实现InvocationHandler接口
public class DynamicSubject implements InvocationHandler {
	private Object sub;
	public DynamicSubject(Object o){
		this.sub = o;//将真实角色的对象保存到sub中
	}
	public Object invoke(Object arg0, Method arg1, Object[] arg2)
			throws Throwable {
		Object o = null;
		System.out.println("before invoke:"+arg1.toString());
		o = arg1.invoke(sub, arg2);//通过反射调用真实角色sub的方法
		System.out.println("after invoke:"+arg1.toString());
		return o;
	}

}

Client.java:

package com.zhb.dynamicproxy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client {

	public static void main(String[] args) throws Exception {
		RealSubject realSubject = new RealSubject();// 创建真实角色的对象
		InvocationHandler invocationHandler = new DynamicSubject(realSubject);// 初始化代理角色
		Class cls = realSubject.getClass();

		Class<?> c = Proxy.getProxyClass(cls.getClassLoader(),
				cls.getInterfaces());// 根据真实角色 构建、返回一个proxy类
		Constructor<?> ctor = c
				.getConstructor(new Class[] { InvocationHandler.class });
		Subject subject2 = (Subject) ctor
				.newInstance(new Object[] { invocationHandler });// 创建一个之前构建的proxy类的接口对象
		subject2.request();
		AnotherSubject subject3 = (AnotherSubject) ctor
				.newInstance(new Object[] { invocationHandler });
		System.out.println(subject3.Hello("world"));

		// Proxy.newProxyInstance等价于上述三个函数,运行时动态生成一个proxy.$Proxy0类,该类实现了真实角色的接口,并返回proxy.$Proxy0的一个对象
		//把需要调用的接口cls.getInterfaces(),以及代理角色invocationHandler告诉 Proxy.newProxyInstance,该函数就会根据你提供的接口动态生成一个proxy.$Proxy0类,
		//并返回该类的一个对象subject,对subject调用相应的方法时,会调用invocationHandler中的invoke()函数,通过反射来调用真实角色的方法。
		Subject subject = (Subject) Proxy.newProxyInstance(
				cls.getClassLoader(), cls.getInterfaces(), invocationHandler);
		subject.request();
		System.out.println(subject.getClass());
		AnotherSubject subject4 = (AnotherSubject) Proxy.newProxyInstance(
				cls.getClassLoader(), cls.getInterfaces(), invocationHandler);
		System.out.println(subject4.getClass() + " " + subject4.Hello("zhb"));
	}

}

运行结果:

before invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
from realsubject
after invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
before invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
after invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
hello world
before invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
from realsubject
after invoke:public abstract void com.zhb.dynamicproxy.Subject.request()
class com.sun.proxy.$Proxy0
before invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
after invoke:public abstract java.lang.String com.zhb.dynamicproxy.AnotherSubject.Hello(java.lang.String)
class com.sun.proxy.$Proxy0 hello zhb

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值