《SpringAOP面试题.docx》由会员分享,可在线阅读,更多相关《SpringAOP面试题.docx(17页珍藏版)》请在第一文库网上搜索。
1、SpringAOP面试题Spring之前已经跟学弟具体聊很详细的10C已经循环依赖问题,接下来要接着为跟学妹们聊另外的一个模块了,那就是AOP,这也是面试官比较喜欢问的一个模块点。什么是AOP?AOP通常叫面向切面编程(Aspect-oriented Programming,简称AOP),它是一种编程范式,通过预编译的方式和运行期动态代理实现程序功能的统一维护的一种技术。通常用来对隔离不同业务逻辑,比如常见的事务管理、口志管理等。同时实现AOP的方式也有两种:cgl ib以及jdk两种方式来实现。为什么要有AOP?假设现在有几个实现方法,需耍做日志处理,正常来说我们只需要手动添加一下日志就可以
2、了,我们都知道在真正的业务代码中,代码行数,以及方法数那是一个天文数字,如果都要手动添加那工作量不现实。本着作为程序员因该想着怎么合理的偷懒的习惯,所以应该想办法提高效率。AOP因此就产生了,说白了 AOP就是通过某种匹配规则去匹配方法,然后再添加对应的日志处理。而本身的实现方式就是通过八SM字节码框架动态生成技术,在程序运行的时候,根据需求(添加文件)动态创建字节码文件,之前讲的设计模式中动态代理模式中也有讲到,大家可以再去复习一下。AOP的核心概念 切面(Aspect):似于Java中的类声明,常用于应用中配置事务或者日志管理。一般使用Aspect注解或者aop:aspect来定义一个切面
3、。 连接点(Join Point):程序执行中的特定点,比如方法执行、处理一个异常等 切点(Pointcut):通过一种规则匹配的正则表达式,当有连接点可以匹配到切点时,就会触发改切点相关联的指定通知。 通知(Advice):在切面中某个连接点采取的动作,通知方式也有5种 around(环绕通知):前后都加 before(前置通知) after (后置通知) exception (异常通知) return(返回通知) 织入(Weaving):链接切面和目标对象创建一个通知对象的过程。A0P其实就是一种编程思想,而这上面的这个点就是编程的具体实现规范。一个应用中可以有多种通知方式所以在A0P中引
4、入一种设计模式责任链模式通过这这种模式来顺序执行每一个通知当然也可以使用0rder注解,配置数字越小,越先执行。关于责任链模式的大家也可以去看看我之前写的设计模式复习一下。A0P的执行过程之前跟大家聊I0C的时候跟大家聊过它的启动过程,同样的AOP也有指定的执行流程,但是需要I0C作为基础。I0C容器启动,用来存放对象 进行对象的实例化和初始化操作,将生成的完成的对象存放到容器中(容器运行中的一些对象比如 BeanFactoryProcesser methodlnterceptore 等还有其他的很多对象) 从创建好的容器中获取需要对象 调用具体的方法开始调用说了这么多理论知识,要想知道里面的
5、具体执行流程,还是老样子,一步一步debug进入源码查看流程了首先还是需要先准备配置一个切面public class LogUtilPointcut (z,execut ion (public * com. ao. bi ng. demo, spring, aop. .*(. )public void pctMethod()Ipublic Object around(ProceedingJoinPoint pjp) throws ThrowableObject ret 二 pjp. proceed。System. out. printin (Around advice)return ret;l
6、public void before。System, out. print In (Before advice);public void after ()System, out. printIn(After advice);Af terReturning (value =pctMethodOpub lie void af ter Re t urn i ng ()System, out- printin (z/AfterReturning advice);pub lie void af terThrow i ng ()SystenL out- println(z/AfterThrowing ad
7、vice);public static void main (Stringn args)ApplicationContext applicat ionContext - new ClassPathXmlApplicationContext (classpath:applicationContext. xml)AopTestDemo aopTestDemo = applicationContext. getBean(AopTestDemo. cl这里配置一个LogUtil的切面demo,五种通知都写了一遍,同时也有一个main方法测试。准备工作做完了就正式开始debug代码了首先在aopTcst
8、Demo里面我们打上断点,此时我们的过去的bean对象aopTestDemo已经是通过动态代理生成的对象了,其中这里面有很多的CALLBACK方法属性。那写方法属性是什么呢?其实这里面就乂跟Spring的拦截器有关,其实就是一种设计模式观察者模式说白了就是对对象的一种行为的监听。通过回调机制来实现通知的功能。那既然是回调方法,那就先进DynamicAdvisedlnterceptor方法中private static class DynamicAdvisodinterceptor implcmonts MethodinI r-i.ii X%iI、)口.泊小八门:public DynamicAd
9、visedlnterceptor (AdvisedSupport advised)this, advised 二 advised;public Object intercept (Object proxy, Method method, ObjJt 口 args, MethodProxy methodProxy) throws ThrowableObject oldProxy 二 nullObject target = null;.TargetSource targetSource = this, advised. getTargctSource();Ii (llii s. adv i sed
10、. exposeProxy) dIWiMMIliMoldProxy = AopContext. setCurrentProxyset ProxyCon text = 1 ru(?;target = targetSource. getTarget ()Class targetClass - target !- null ? targetegetClass(|ListObject chain . this. advised.ptorsAndDynamicInterceptionAdvice (method, targetClass)Object retVal:Object口 argsToUse ,
11、 AopProxyUtils. adaptArgumentsIfNesary (method, args)retVal = methodProxy. invoke (target, argsToUse)retVal 二(new CglibAopProxy.hodinvocation (proxy, target, method, args, targetClass, chain,y)- proceed () ;lretVal = CglibAopProxy. processReturnType(proxvarl6retVal;finally if (target != null & ! tar
12、getSource. isStaticO)AopContext. setCurrentProxy (oldProxy);return varl6;在DynamicAdvisedlnterceptor中有一个List chain这里获取到我们配置的通知方法从上面的截图可以看到Spring先是把所有的通知获取到,放在一个list集合对象中,因为此时list不为空所以就乂会走到 通过CglibMcthodlnvocation来启动advico通知这一步的流程中ublic class ReflectiveMethodlnvocation implements ProxyMethodlnvocation
13、,Cloneableprotected final Object proxy;protected f inal Object target;protected final Method method;protected Object arguments = new Object0;private final Class targetClass;f* Lazily initialized map of user-specific attributes for this invocaprivate Map userAttributes;* List of Methodlnterceptor and
14、 InterceptorAndDynamicMethodMatcheiprotected final List interceptorsAndDynamicMethodMatchers;/* Index from 0 of the current interceptor were* T until we invoke: then the current interceptor.private int currentInterceptorIndex = T;省略其他的方法Overridepublic Object proceed。throws Throwable/ lie start wi th
15、 an index of -7 and increment early. I/从索引为T的拦截器还是调用,并且按顺序递增,如果整个List chain中if (this, currentInterceptorIndex =二 this. interceptorsAndDynamicMethodMatchers. size() - 1)0 ;mObject interceptorOr Intercept ionAdvicethis. interceptorsAndDynamicMethodMatchers. get(+this. currentInterceptorInde| if (interceptorOrlnterc