竹笋

首页 » 问答 » 灌水 » 大家理解SpringAop利器Pr
TUhjnbcbe - 2023/11/3 20:47:00
白癜风发红怎么办 http://m.39.net/news/a_5927676.html

工程结构图:

概要

前面两三篇,介绍了springaop得以实现的利器:ProxyFactory。

ProxyFactory,全称:org.springframework.aop.framework.ProxyFactory,spring帝国springaop*工厂boss,职责就是生产proxy,即,代理工厂。

通过下面几行代码,就能生成一个代理对象,而且我们还加了了一个环绕通知:

输出如下:

本讲,我们来讲讲,背后的故事。

ProxyFactory如何构造

其一共有如下几个重载的构造函数:

无参构造函数ProxyFactory(Objecttarget)指定targetProxyFactory(Class[]proxyInterfaces)指定代理类要实现的接口ProxyFactory(ClassproxyInterface,Interceptorinterceptor)指定代理类要实现的接口,以及一个切面ProxyFactory(ClassproxyInterface,TargetSourcetargetSource)指定代理类要实现的接口,以及一个targetSource,targetSource类似于一个targetFactory,通过其,间接获取target因为springaop源码里,默认就使用了的是无参构造函数,这里我们也以无参构造函数来讲解。

我们知道,构造函数调用时,如果这个类有父类,还得先调用父类的构造函数。恰巧,这个类就有父类:

其中,ProxyConfig没有显示定义的构造函数,所以只有默认的无参构造函数。所以,

会先调用ProxyConfig的无参构造函数;调用AdvisedSupport的无参构造函数,如下:/***No-argconstructorforuseasaJavaBean.*/publicAdvisedSupport(){initMethodCache();}/***Initializethemethodcache.*/privatevoidinitMethodCache(){this.methodCache=newConcurrentHashMapMethodCacheKey,ListObject(32);}

接下来,调用ProxyCreatorSupport的无参构造函数:

/***CreateanewProxyCreatorSupportinstance.*/publicProxyCreatorSupport(){this.aopProxyFactory=newDefaultAopProxyFactory();}

4.调用ProxyFactory的无参构造函数

/***CreateanewProxyFactory.*/publicProxyFactory(){}

其中,比较有的讲的,主要是第三个步骤,即ProxyCreatorSupport的无参构造函数。

这一步呢,new了一个DefaultAopProxyFactory,不过,暂时还没用到它。

构造完了,接下来,就是各种配置上场的时候了。

配置ProxyFactory

好歹这也是一响当当的工厂,但是吧,要生产啥呢?总得有个方向吧。你是一个ProxyFactory,代理工厂,你要代理谁?代理卖火车票,还是代理卖房呢?注意,这里我说的是卖火车票,和卖房。

这说明啥,说明我屁股是坐在卖方的,是一方,是要卖房的一方。因为啥呢,因为我现在的target,是卖方,我是作为卖方的代表(即,代理)来出现的。

target很重要,这个直接决定了我们工厂的方向。比如,假设翻转一下,代理买方。比如,现在中国人,有钱人很多,很多人就去国外买房,比如澳洲、日本、东南亚啥的,但是呢,你对当地不了解,所以,就催生了当地的一批华人,来帮助大陆中国人在那边买房,此时,他们就是我们的代理。我们呢,就是他们的target。

ok,大家想必理解了,ProxyFactory要生产啥,主要还是要有个定位,看看屁股坐哪边。所以,我们作为代码世界的王者,就要负责来定方向。

配置target

Performerperformer=newPerformer();proxyFactory.setTarget(performer);

定了target,基本定了一半了。

当然,你也不可以不直接定target,定接口也行。

配置接口,即代理要具备的功能

proxyFactory.addInterface(Perform.class);

配置额外的切面(可选)

这个步骤是可选的,你也可以没有切面,没有的话,默认就是代理啥事都不帮你做,你让他帮你分析房产,结果人只收钱不干活。

我们这里的切面,是在target唱歌完了之后,输出一句话:要行礼。

额外的一些配置

当然了,作为一个齐备的工厂,还是要支持一些客户的定制功能的。比如:

从ProxyConfig继承来的一些方法

比如,有的客户说,我要cglib创建代理,有的说,我要jdk。ok,这个就满足你了。再比如,isExposeProxy,这个可以把生成的代理通过一个api提供给你,你可以在target方法内,拿到代理对象。

2.从AdvisedSupport继承来的功能

这个也简单,基本就是我们前面那几个配置的重载方法,增删改查嘛。

3.从ProxyCreatorSupport继承来的功能

这个嘛,基本就是扩展了一下,搞了点事件/监听的机制,方便我们扩展。

ok,配也配好了,是不是该把代理对象给人家了。

根据配置,生成代理

我写着写着,发现这个东西,很像开一个煎饼店,比如根据客户要求:要鸡蛋、培根、鸡排啥的(这个就是对应上面的配置部分);然后,这一步,我们作为店老板,就开始去根据客户的要求,煎煎饼!

Performproxy=(Perform)proxyFactory.getProxy();

煎饼的过程如何,我们来看看:

publicObjectgetProxy(){returncreateAopProxy().getProxy();}

是不是很简单,其实,我们应该分为两步来看:

publicObjectgetProxy(){/***AopProxy是一个接口,实现类有jdk动态代理、cglib两种*/AopProxyaopProxy=createAopProxy();returnaopProxy.getProxy();}

选择客户要求,选择合适的煎锅

这一步,就是对应:

/***AopProxy是一个接口,实现类有jdk动态代理、cglib两种*/AopProxyaopProxy=createAopProxy();

因为我们这里,AopProxy有两种实现,要用哪一种,要根据之前的配置来,比如,指定了proxyTargetClass,那就是要用cglib;否则就用jdk动态代理。

我们具体看看:

这里,先获取了AopProxyFactory,这里呢,拿到的,就是之前我们构造函数时候那个。

/***ReturntheAopProxyFactorythatthisProxyConfiguses.*/publicAopProxyFactorygetAopProxyFactory(){returnthis.aopProxyFactory;}

这里拿到DefaultAopProxyFactory后,程序会调用其createAopProxy(this),且把当前对象都传进去了,当前对象是谁?就是ProxyFactory代理工厂本厂。

具体的创建代码如下:

注意看最上面的if判断:

if(config.isOptimize()

config.isProxyTargetClass()

hasNoUserSuppliedProxyInterfaces(config))

是不是,如果isProxyTargetClass为true,或者hasNoUserSuppliedProxyInterfaces,按里面理解,没有提供接口,则会走下面的逻辑,去用cglib创建代理。

因为我们这里是提供了接口的,所以,会new一个:jdk的动态代理。

这里可以看到,构造函数很简单,就是把代理工厂本厂的引用传给他了。我们前面配了那么多东西在ProxyFactory上,怎么能说给人就给人?

废话,不给JdkDynamicAopProxy,它怎么创建代理呢?

JdkDynamicAopProxy揭秘

这个类,我直接给大家说,其实现了两个接口:

代理接口:AopProxy

2.这个接口就是获取代理对象。

3.java.lang.reflect.InvocationHandler接口

这个接口,熟悉jdk动态代理的就知道,拦截的逻辑就写在这里面。我们大概可以猜测,代理对象调用方法时,就会被拦截到这个方法里面来处理。

生成代理对象

前面,我们已经讲解了这一步了:

马上就要调用getProxy来生成代理对象。

这里就简单的几步:

获取要代理的全部接口Class[]proxiedInterfaces=AopProxyUtils.

1
查看完整版本: 大家理解SpringAop利器Pr