博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
代理模式与它在源码中的运用
阅读量:6222 次
发布时间:2019-06-21

本文共 7433 字,大约阅读时间需要 24 分钟。

代理是指一个包装了真实访问对象的类,以便控制对真实类的访问

访问流程如下

public interface SubjectInterface {    void hi();}public class RealSubject implements SubjectInterface {    @Override    public void hi() {        System.out.print("hi");    }}public class SubjectProxy implements SubjectInterface{    private RealSubject r;    public SubjectProxy() {        r=new RealSubject();    }    @Override    public void hi() {        System.out.println("proxy");        r.hi();    }}public class Client {    public static void main(String[] args) {       SubjectInterface subject = new SubjectProxy();        subject.hi();    }}复制代码

此时RealSubject作为代理对象的一个属性字段,在运行之前就会生成RealSubject的字节码文件,这种方式也称作静态代理

动态代理

被代理的类在运行时动态生成的,编译的时候并没有生成RealSubject

使用JDK实现动态代理

jdk实现动态代理必须有实现接口InvocationHandler的处理类,用于执行被代理类的方法

public class SubjectInvocationHandler implements InvocationHandler {    private Object myproxy;    public SubjectInvocationHandler(Object proxy) {        this.myproxy = proxy;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("invocation handler");        method.invoke(myproxy,args);        return null;    }}复制代码

客户端通过使用java.lang.reflect.Proxy自行创建代理,然后调用目标方法即可

public class Client {    public static void main(String[] args) {    //classloader会被用来验证是否可以加载传入的接口,     SubjectInterface proxy = (SubjectInterface) Proxy.newProxyInstance(SubjectInterface.class.getClassLoader()     , new Class[]{SubjectInterface.class}     , new SubjectInvocationHandler(new RealSubject()));     proxy.hi(); }复制代码

访问流程如下

生成代理proxy class阶段

代理对象会在内部缓存,如果没有缓存则会由ProxyClassFactory新生成。

首先会做接口校验,比如是否可以从提供的classLoader获取接口

Class
interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); }复制代码

验证完毕后,会读取接口的class文件使用的是 ProxyGenerator.generateProxyClass,可以看到它会对整个的class文件的字节做读取

private byte[] generateClassFile() { ... dout.writeInt(0xCAFEBABE); ...}复制代码

最后调用native方法生成代理对象,并存入缓存

获取proxy的构造函数

构造函数指定的参数就是InvocationHandler

创建实例

调用构造函数,传入自定义的invocationHandler,自此生成了一个proxy实例,且实例本身会实现传入的接口,代码实例生成的对象如下所示

public final class $Proxy0 extends Proxy implements SubjectInterface {    ...       public final void hi() throws  {        try {           //这里的h即Proxy中的InvocationHandler,也就是用户自定义的InvocationHanlder           //这个this对象代表的也就是 $Proxy0 本身            super.h.invoke(this, m3, (Object[])null);        } catch (RuntimeException | Error var2) {            throw var2;        } catch (Throwable var3) {            throw new UndeclaredThrowableException(var3);        }    }    ...}复制代码

使用CGlib动态代理

引入CGlib之后,执行如下代码即可

public class Client {    public static void main(String[] args) {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(RealSubject.class);        enhancer.setCallback(new MethodInterceptor() {            @Override            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {                System.out.println("cglib:"+method.getName());                methodProxy.invokeSuper(o, objects);                return o;            }        });        RealSubject realSubject = (RealSubject)enhancer.create();        realSubject.hi();    }}复制代码

动态代理在spring aop中的运用

spring中默认使用DefaultAopProxyFactory

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {			Class
targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { //对于接口使用的是JDK return new JdkDynamicAopProxy(config); } //其余使用Cglib作为动态代理的实现 return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }复制代码

JdkDynamicAopProxy

它实现了InvocationHandler和AopProxy。AopProxy主要是负责提供getProxy,实现为

@Override	public Object getProxy() {		return getProxy(ClassUtils.getDefaultClassLoader());	}	@Override	public Object getProxy(@Nullable ClassLoader classLoader) {		if (logger.isTraceEnabled()) {			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());		}		Class
[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }复制代码

当有需要执行的方法的时候,则是执行invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ... 	invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);	// Proceed to the joinpoint through the interceptor chain.	retVal = invocation.proceed(); ...}public Object proceed() throws Throwable {    ...    if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {    //这里会执行AfterReturningAdviceInterceptor、AspectJAfterThrowingAdvice等等方法    	return dm.interceptor.invoke(this);    }    ...}复制代码

CglibAopProxy

它实现了AopProxy,核心的生成代理的方式如下

public Object getProxy(@Nullable ClassLoader classLoader) { ... Enhancer enhancer = createEnhancer(); if (classLoader != null) {		enhancer.setClassLoader(classLoader);		if (classLoader instanceof SmartClassLoader &&				((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {			enhancer.setUseCache(false);		}	}	enhancer.setSuperclass(proxySuperClass);	enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));	enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);	enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));	Callback[] callbacks = getCallbacks(rootClass);	Class
[] types = new Class
[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks); ...}private Callback[] getCallbacks(Class
rootClass) throws Exception {...Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);...Callback[] mainCallbacks = new Callback[] { aopInterceptor, // for normal advice targetInterceptor, // invoke target without considering advice, if optimized new SerializableNoOp(), // no override for methods mapped to this targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised)};...else { callbacks = mainCallbacks;}...}复制代码

以DynamicAdvisedInterceptor为例,它就实现了MethodInterceptor

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {    ...    //同样在此处去运行具体的Advice    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();    ...}复制代码

通常可以使用Proxy的情况

  1. 虚代理:根据需要创建开销很大的对象,只有用到时才创建
  2. 保护代理:控制对原始对象的访问
  3. 智能指引:在访问对象时附加了一些操作,比如对象没有引用时释放它
  4. 远程代理:为一个对象在不同的地址空间提供局部代表

转载地址:http://xerja.baihongyu.com/

你可能感兴趣的文章
jQuery获取数组对象的值
查看>>
Android+struts2+json方式模拟手机登录功能
查看>>
#大学#汇编指令查询
查看>>
mono for android software自动更新
查看>>
版本管理工具——Git和TortoiseGit(乌龟Git)
查看>>
开源SIP服务器加密软件NethidPro升级
查看>>
linux的简单命令
查看>>
我的友情链接
查看>>
大型网站技术架构(一)大型网站架构演化
查看>>
百度页面分享插件源代码
查看>>
易宝典文章——玩转Office 365中的Exchange Online服务 之六 了解Exchange Online对于邮箱使用的限制...
查看>>
确定jdk是32位版本还是64位版本
查看>>
linux下文件删除的原理
查看>>
python os.path模块
查看>>
评"抄袭就是生产力:评中国盛行的成功学逻辑"
查看>>
红客专用电脑安全工具箱 v 1.9
查看>>
$.noConflict()方法--常用的方式
查看>>
MongoDB的真正性能
查看>>
使用Zabbix监控windows服务
查看>>
win7 从硬盘重装操作系统(64位)
查看>>