当前位置: 首页 > news >正文

Spring源码-AOP具体源码

1.类ProxyFactory

核心方法:getProxy

1.DefaultAopProxyFactory#createAopProxy

判断使用JDK还是CGLIB动态代理的代码如下:

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {// 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快// 或者isProxyTargetClass为true,// 或者被代理对象没有实现接口,// 或者只实现了SpringProxy这个接口// 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理// 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口// 是不是在GraalVM虚拟机上运行if (!NativeDetector.inNativeImage() &&(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)) {//被代理的类 是接口return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}
}

判断该使用哪种技术生成代理对象

config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config),判断是否优化、是否代理目标类、是否没有接口。满足这个条件,返回CGLIB代理对象;不满足,就返回JDK代理对象。

同时还会判断,判断:targetClass.isInterface() || Proxy.isProxyClass(targetClass),如果被代理的类是接口,那就返回JDK代理对象;如果类是被JDK代理的类,那继续使用JDK代理对象。

(isOptimize()表示Spring启动优化,那就使用CGLIB;isProxyTargetClass 表示代理的是类,JDK只能代理接口;hasNoUserSuppliedProxyInterfaces表示用户有没有addInterface)

2.getProxy

核心:通过不同的技术,产生代理对象(有两种实现方法,CGLIB和JDK动态代理)

2.Jdk生成的代理对象的执行流程

核心方法:JdkDynamicAopProxy#invoke

1.targetSource = this.advised.targetSource

拿到被代理对象

2.如果接口中的是equals方法或者hasCode方法,那它们不用走代理

3.if (this.advised.exposeProxy),true-->把代理对象放到ThredLocal中

如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中

4.target = targetSource.getTarget();Class<?> targetClass

拿到被代理对象和代理类

5.chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(2.1详细讲

代理对象在执行某个方法时,根据方法筛选出匹配的 Advisor ,并适配成 Interceptor生成chain链。(生成MethodIntercept链)

6.如果chain.isEmpty()(没有代理逻辑),则调用invokeJoinpointUsingReflection(直接执行 被代理对象的方法)

7.如果有代理逻辑,invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain),将chain 组合成invocation (2.2详解ReflectiveMethodInvocation)

retVal = invocation.proceed();// 执行MethodIntercept逻辑

@Override@Nullablepublic Object proceed() throws Throwable {// We start with an index of -1 and increment early.// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1// 当调用完了 最后一个interceptor后 就会执行被代理方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}// currentInterceptorIndex初始值为-1Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor// 如果没有匹配则递归调用proceed()方法,调用下一个interceptorif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());// 动态匹配,根据方法参数匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 不匹配则执行下一个MethodInterceptorreturn proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归// 比如MethodBeforeAdviceInterceptorreturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}

invoke->proceed->invoke->proceed,链路调用实现AOP逻辑

8.结束

2.1getInterceptorsAndDynamicInterceptionAdvice的筛选逻辑

代理对象在执行某个方法时,根据方法筛选出匹配的 Advisor ,并适配成 Interceptor,生成chain链。(生成MethodIntercept链)

核心:所有Advice都会封装成Advisor,最终都会转化为MethodInterceptor

1.advisors = config.getAdvisors()

从ProxyFactory中拿到所设置的Advice(config就是ProxyFactory)

2.遍历每一个Advisor,筛选出符合条件的Advisor

3.先看class是否匹配class匹配通过,再看方法是否匹配(现在只拿MethodMatcher中的matches进行匹配)

4.如果都匹配,执行interceptors = registry.getInterceptors,将Advisor封装成为MethodInterceptor

在这里使用到设配器模式,将advisor中的advice适配成MethodInterceptor(适配的代码如下)

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {List<MethodInterceptor> interceptors = new ArrayList<>(3);Advice advice = advisor.getAdvice();// 取出Adviceif (advice instanceof MethodInterceptor) {interceptors.add((MethodInterceptor) advice);}// 将Advice适配成MethodInterceptorfor (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}if (interceptors.isEmpty()) {throw new UnknownAdviceTypeException(advisor.getAdvice());}return interceptors.toArray(new MethodInterceptor[0]);
}

三个适配器

  • MethodBeforeAdviceAdapter():before
  • AfterReturningAdviceAdapter(): AfterRurening
  • ThrowsAdviceAdapter(): Throws

注意:afterThrowing限制方法的参数是1个或者4个。部分核心代码如下:

class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {@Overridepublic boolean supportsAdvice(Advice advice) {return (advice instanceof AfterReturningAdvice);}@Overridepublic MethodInterceptor getInterceptor(Advisor advisor) {AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();return new AfterReturningAdviceInterceptor(advice);}}
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {private final AfterReturningAdvice advice;/*** Create a new AfterReturningAdviceInterceptor for the given advice.* @param advice the AfterReturningAdvice to wrap*/public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Override@Nullablepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}}

4.1.判断isRuntime(),如果runtime为true,再包装成InterceptorAndDynamicMethodMatcher(runtime为true->进行入参匹配),还需要看MethodMatcher中的matches是否可以匹配,如果匹配,才可以执行代理逻辑。

if (match) {// 如果匹配则将Advisor封装成为Interceptor,当前Advisor中的Advice可能即是MethodBeforeAdvice,也是ThrowsAdviceMethodInterceptor[] interceptors = registry.getInterceptors(advisor);if (mm.isRuntime()) {// Creating a new object instance in the getInterceptors() method// isn't a problem as we normally cache created chains.for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}
}

2.2 ReflectiveMethodInvocation的执行逻辑

1.invocation.proceed

执行 MethodIntercept逻辑

2.invokeJoinpoint

当Interceptor执行完,就执行被代理的方法

3.满足方法的匹配(runtime为true),根据方法参数匹配

如果匹配,调用interceptor.invoke,执行被包装的代理逻辑

如果不匹配,则执行下一个MethodInterceptor,调用proceed()

3.SpringAOP的实现逻辑

核心注解:@EnableAspectJAutoProxy-->@Import(AspectJAutoProxyRegistrar.class)-->registerBeanDefinitions--> registerAspectJAnnotationAutoProxyCreatorIfNecessary-->forceAutoProxyCreatorToUseClassProxying

解释:注册一个 AnnotationAwareAspectJAutoProxyCreator 类型的Bean, beanName为AUTO_PROXY_CREATOR_BEAN_NAME(AnnotationAwareAspectJAutoProxyCreator就是BeanPostProcessor)

forceAutoProxyCreatorToUseClassProxying是将注解中的属性注册到BeanDefinition中,包含proxyTargetClass和exposeProxy。

3.1AOP代理对象的产生时机

当生成Bean的时候,调用doCreateBean-->initializeBean-->applyBeanPostProcessorsAfterInitialization(进入初始化后逻辑),

进行如下判断:拿到所有的BeanPostProcessor,包括AnnotationAwareAspectJAutoProxyCreator,如果存在这个BeanPostProcessor,则走代理逻辑,生成代理对象。

进入postProcessAfterInitialization生成代理对象的逻辑(类AbstractAutoProxyCreator)

(注意:AnnotationAwareAspectJAutoProxyCreator的父类就是AbstractAutoProxyCreator)

AbstractAutoProxyCreator#wrapIfNecessary的代码如下:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aopif (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 当前正在创建的Bean不用进行AOP,比如切面Beanif (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象// 此处根据类以及类中的方法去匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前执行的方法去匹配Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {// advisedBeans记录了某个Bean已经进行过AOP了this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;
}

1.调用wrapIfNecessary

2.判断FALSE.equals(this.advisedBeans.get(cacheKey))

表示已经判断过了的bean,false表示此bean不需要进行AOP

3.判断isInfrastructureClass

表示当前正在创建的Bean不用进行AOP,比如切面Bean、Advice、Pointcut、Advisor、AopInfrastructureBean,同时调用advisedBeans.put(cacheKey, Boolean.FALSE):把不进行AOP的bean放到缓存

4.判断shouldSkip(模版方法)

留给子类扩展,子类可以定义哪些Bean不需要AOP

5.Object[] specificInterceptors = getAdvicesAndAdvisorsForBean

找到所有bean中的Advisor,内容很多,在3.2。

6.如果specificInterceptors!=null,调用

createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)),生成代理对象,调用addAdvisors-->setTargetSource-->proxyFactory.getProxy(classLoader)

在执行的时候还会对Advisor筛选,执行符合不同方法的Advisor(对于一个bean,并不是所有的Adivisor都生效

3.2getAdvicesAndAdvisorsForBean的实现逻辑

判断某个bean是否需要进行AOP,匹配到bean的所有Advisor(第一次匹配)。bean在执行方法的时候还会进行一次匹配,细粒度的匹配(pointcut匹配)(第二次匹配)。(一共两次)

getAdvicesAndAdvisorsForBean(类AbstractAdvisorAutoProxyCreator)-->findEligibleAdvisors(找到合格的Advisors)

1.调用findCandidateAdvisors,找到所有的Advisor

1.1findAdvisorBeans

先找到 所有Advisor类型 的Bean对象.findCandidateAdvisors

具体是:从beanFactory拿到所有Advisor的beanName,找到Advisor的bean添加到list中,然后return

BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors:本方法会被多次调用,因为一个Bean在判断要不要进行AOP时,都会调用这个方法

获取切面类中没有加@Pointcut的方法,进行遍历生成Advisor

ReflectiveAspectJAdvisorFactory#getAdvisorMethods:

private List<Method> getAdvisorMethods(Class<?> aspectClass) {List<Method> methods = new ArrayList<>();// 拿到切面类中所有没有加@Pointcut的方法ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);// 对方法进行排序,按注解和方法名字进行排序if (methods.size() > 1) {methods.sort(adviceMethodComparator);}return methods;
}

1.2advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()

从所有切面中解析,得到Advisor对象,也就是解析加了@Aspect注解的bean

具体是:找出来Factory中所有bean,然后判断有无@Aspect注解,拿到加了@Aspect注解的bean,factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName),把这个bean封装成BeanFactoryAspectInstanceFactory对象,利用BeanFactoryAspectInstanceFactory来解析Aspect类。

调用getAdvisors,拿到Bean的类型和name,getAdvisorMethods(获取切面类中所有没有加Pointcut注解的方法),methods.sort,先根据Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的顺序排序,然后根据方法的名字排序。

调用getAdvisor,将方法生成Advisor(拿到所有带Pointcut内容的Advisor),他会调用expressionPointcut = getPointcut,拿到当前方法所对应的Pointcut对象,但是注意:如果当前方法上是这么写的@After("pointcut()"),那么此时得到的Pointcut并没有去解析pointcut()得到对应的表达式,然后调用InstantiationModelAwarePointcutAdvisorImpl,拿到所有带Pointcut内容的Advisor,之后核心调用getAdvice(解析method上面的注解),根据不同的注解生成Advice对象。

2.调用eligibleAdvisors = findAdvisorsThatCanApply,进行筛选,将找到的所有Advisor和userService的方法进行匹配,找到符合userServicce方法的Advisor(利用方法过滤器)

3.sortAdvisors,对Advisor进行排序,按 Ordered接口、@Order 注解进行排序

3.3 AOP的执行逻辑

Advisor在执行的时候,就会进到这个方法getAdvice(类InstantiationModelAwarePointcutAdvisorImpl

getAdvice-->instantiateAdvice-->advice =getAdvice(this.aspectJAdviceMethod,...)

1.getAspectClass

拿到切面类

2.aspectJAnnotation =findAspectJAnnotationOnMethod

拿到当前candidateAdviceMethod方法上的注解信息

3.根据不同的注解生成不同的Advice,然后执行。代码如下:

@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();validate(candidateAspectClass);// 拿到当前candidateAdviceMethod方法上的注解信息AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}// If we get here, we know we have an AspectJ method.// Check that it's an AspectJ-annotated classif (!isAspect(candidateAspectClass)) {throw new AopConfigException("Advice must be declared inside an aspect type: " +"Offending method '" + candidateAdviceMethod + "' in class [" +candidateAspectClass.getName() + "]");}if (logger.isDebugEnabled()) {logger.debug("Found AspectJ method: " + candidateAdviceMethod);}AbstractAspectJAdvice springAdvice;// 按不同的注解类型得到不同的Adviceswitch (aspectJAnnotation.getAnnotationType()) {case AtPointcut:if (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;case AtAround:// @AroundspringAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtBefore:springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfter:springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtAfterReturning:springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}break;case AtAfterThrowing:springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {springAdvice.setThrowingName(afterThrowingAnnotation.throwing());}break;default:throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}// Now to configure the advice...springAdvice.setAspectName(aspectName);springAdvice.setDeclarationOrder(declarationOrder);String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;
}

示例,如果使用After注解,After类的代码如下:核心是invoke方法

public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {super(aspectJBeforeAdviceMethod, pointcut, aif);}@Override@Nullablepublic Object invoke(MethodInvocation mi) throws Throwable {try {return mi.proceed();}finally {invokeAdviceMethod(getJoinPointMatch(), null, null);}}@Overridepublic boolean isBeforeAdvice() {return false;}@Overridepublic boolean isAfterAdvice() {return true;}}

补充:@Around中使用ProceedJoinPoint,其他的注解都是使用JoinPoint。


http://www.mrgr.cn/news/43610.html

相关文章:

  • Electron Vue框架环境搭建 Vue3环境搭建
  • 一款基于.NET开发的简易高效的文件转换器
  • Nexus制品库搭建(maven)
  • Singleton(单例模式)
  • 队列的实现与讲解
  • 量子计算:下一次科技革命的引擎
  • 1分钟搞懂K8S中的NodeSelector
  • 银从法律法规_20
  • HugginngFace的Trainer的常见用法
  • Python使用matplotlib绘制图形大全(曲线图、条形图、饼图等)
  • 二叉搜索树 (BST) 节点插入、查找、删除、获取最大值、最小值和中序遍历排序等功能
  • 每日一题|134. 加油站|循环数组单次遍历
  • PriorityQueue分析
  • 数据结构阶段测试2的一点小补充
  • FRP搭建内网穿透:云服务端 + 家用Linux/Windows主机【2024】
  • 【ShuQiHere】Linux 系统内存清理指南:优化内存使用,提升系统性能
  • centos7安装配置python3环境
  • 【C++ 真题】B2049 最大数输出
  • CPU和GPU的区别
  • springboot中配置优先级