文章结构
- 以
postProcessAfterInstantiation开篇 - 所有的bean在初始化之后都会调用这个方法
- 在这里获取到之前加载到的所有的Advisor,和类的所有方法一一匹配
- 当类具有匹配Advisor的时候就可以为这个类生成具体的代理了
在之前的2篇文章:AOP源码分析(一)AOP源码分析(二)
中,我们搭建了SpringAOP源码分析的环境,介绍了@EnableAspectJAutoProxy注解和postProcessBeforeInstantiation方法是如何加载所有Advisor的。本篇文章则将描述一下AOP中剩余的实现逻辑
postProcessAfterInitialization
这个方法是在bean实例化之后调用的,它是适用于所有需要被代理的类的
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {//往下看return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {//如果已经处理过if (beanName != null && this.targetSourcedBeans.contains(beanName)) {return bean;}//如果当前类是增强类if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}//查看类是否是基础设施类,或者是否被排除if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}//校验此类是否应该被代理,获取这个类的AdvisorObject[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);//如果获取到了Advisor则需要针对Advisor创建代理if (specificInterceptors != DO_NOT_PROXY) {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;}
上方这段代理一共有两个重点,getAdvicesAndAdvisorsForBean和createProxy这两个方法
获取Advisors
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {//往下看List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {//获取容器中的所有AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();//验证beanClass是否该被代理,如果应该,则返回适用于这个bean的AdvisorList<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
上方这个获取Advisor又分成了2部分,获取全部和根据全部处理bean相关的
获取全部Advisor
上一篇postProcessBeforeInstantiation的也有这个过程
protected List<Advisor> findCandidateAdvisors() {// 调用父类的方法加载配置文件中的AOP声明(注解与XML都存在的时候)List<Advisor> advisors = super.findCandidateAdvisors();//往下看if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}
下面的方法就是获取所有的Advisor的代码实现了,方法比较长,不过主要逻辑很少。
1.获取所有beanName
2.找出所有标记Aspect注解的类
3.对标记Aspect的类提取Advisor
public List<Advisor> buildAspectJAdvisors() {List<String> aspectNames = this.aspectBeanNames;if (aspectNames == null) {synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {List<Advisor> advisors = new LinkedList<>();aspectNames = new LinkedList<>();//获取所有的beanString[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {//校验不合法的类,Spring的一个扩展点,可以从子类中做排除切面的操作if (!isEligibleBean(beanName)) {continue;}//获取bean的类型Class<?> beanType = this.beanFactory.getType(beanName);if (beanType == null) {continue;}//是否带有Aspect注解if (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);AspectMetadata amd = new AspectMetadata(beanType, beanName);if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);//解析所有的Advisor方法,下面说List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);if (this.beanFactory.isSingleton(beanName)) {this.advisorsCache.put(beanName, classAdvisors);}else {this.aspectFactoryCache.put(beanName, factory);}advisors.addAll(classAdvisors);}else {if (this.beanFactory.isSingleton(beanName)) {throw new IllegalArgumentException("Bean with name '" + beanName +"' is a singleton, but aspect instantiation model is not singleton");}MetadataAwareAspectInstanceFactory factory =new PrototypeAspectInstanceFactory(this.beanFactory, beanName);this.aspectFactoryCache.put(beanName, factory);advisors.addAll(this.advisorFactory.getAdvisors(factory));}}}this.aspectBeanNames = aspectNames;return advisors;}}}if (aspectNames.isEmpty()) {return Collections.emptyList();}List<Advisor> advisors = new LinkedList<>();for (String aspectName : aspectNames) {List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);if (cachedAdvisors != null) {advisors.addAll(cachedAdvisors);}else {MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);advisors.addAll(this.advisorFactory.getAdvisors(factory));}}return advisors;}
接下来就是各个Advisor的获取方法的实现
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {//获取所有Aspect类、类名称、并校验Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();validate(aspectClass);MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);List<Advisor> advisors = new LinkedList<>();//取出类的所有方法for (Method method : getAdvisorMethods(aspectClass)) {//获取Advisor方法,往下看Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);if (advisor != null) {advisors.add(advisor);}}// 如果需要增强且配置了延迟增强则在第一个位置添加同步实例化Advisor方法if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);advisors.add(0, instantiationAdvisor);}// 获取属性中配置DeclareParents注解的Advisorfor (Field field : aspectClass.getDeclaredFields()) {Advisor advisor = getDeclareParentsAdvisor(field);if (advisor != null) {advisors.add(advisor);}}return advisors;}
普通Advisor的获取
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName) {validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());//获取切点AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());if (expressionPointcut == null) {return null;}//根据切点生成Advisorreturn new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}
上方代码又分为了两部分,先看一下切点信息的获取
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {this.declaredPointcut = declaredPointcut;this.declaringClass = aspectJAdviceMethod.getDeclaringClass();this.methodName = aspectJAdviceMethod.getName();this.parameterTypes = aspectJAdviceMethod.getParameterTypes();this.aspectJAdviceMethod = aspectJAdviceMethod;this.aspectJAdvisorFactory = aspectJAdvisorFactory;this.aspectInstanceFactory = aspectInstanceFactory;this.declarationOrder = declarationOrder;this.aspectName = aspectName;if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {Pointcut preInstantiationPointcut = Pointcuts.union(aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);this.lazy = true;}else {this.pointcut = this.declaredPointcut;this.lazy = false;//初始化对应的Advisor器,重点this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);}}
到这里之后获取所有的Advisor这个流程就快要完毕了
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {//往下看Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,this.aspectInstanceFactory, this.declarationOrder, this.aspectName);return (advice != null ? advice : EMPTY_ADVICE);}public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();validate(candidateAspectClass);AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}if (!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;//根据不同的注解类型封装不同的Advisor器switch (aspectJAnnotation.getAnnotationType()) {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;case AtAround:springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;case AtPointcut:if (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;default:throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}springAdvice.setAspectName(aspectName);springAdvice.setDeclarationOrder(declarationOrder);String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;}
获取匹配Advisor
经过上方的长篇大论,我们终于完成了所有的Advisor器的解析,还记得刚才的方法走到哪了么
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {//获取全部AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
接下来看看怎么为当前的Bean匹配自己的增强吧
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {//往下看return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}}public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();for (Advisor candidate : candidateAdvisors) {//处理引介Advisor,重点,再往下看if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {continue;}//对普通bean的处理if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
引介Advisor与普通bean的处理最后都是进的同一个方法,只不过是引介Advisor的第三个参数默认使用的false
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {//如果存在排除的配置if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;//往下看return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {return true;}}public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");//切点上是否存在排除类的配置if (!pc.getClassFilter().matches(targetClass)) {return false;}//验证注解的作用域是否可以作用于方法上MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {return true;}IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));classes.add(targetClass);for (Class<?> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {//获取类所实现的所有接口和所有类层级的方法,循环验证if ((introductionAwareMethodMatcher != null &&introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||methodMatcher.matches(method, targetClass)) {return true;}}}return false;}
现在所有的bean对应的Advisor都已经获取到了,那么就可以根据类的所有Advisor数组创建代理
创建代理
回到最上方开始获取Advisor的地方,当Advisor获取到之后就可以执行下面这个操作了
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}ProxyFactory proxyFactory = new ProxyFactory();使用proxyFactory对象copy当前类中的相关属性proxyFactory.copyFrom(this);//判断是否使用Cglib动态代理if (!proxyFactory.isProxyTargetClass()) {//如果配置开启使用则直接设置开启if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {//如果没有配置开启则判断bean是否有合适的接口使用JDK的动态代理(JDK动态代理必须是带有接口的类,如果类没有实现任何接口则只能使用Cglib动态代理)//关于代理的基础知识可以参考我的另一篇文章:https://mp.weixin.qq.com/s/1DRmvuky5_NMRcH-toTLqQevaluateProxyInterfaces(beanClass, proxyFactory);}}//添加所有AdvisorAdvisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);//设置要代理的类proxyFactory.setTargetSource(targetSource);//Spring的一个扩展点,默认实现为空。留给我们在需要对代理进行特殊操作的时候实现customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}//使用代理工厂获取代理对象return proxyFactory.getProxy(getProxyClassLoader());}
获取代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}return getAopProxyFactory().createAopProxy(this);}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)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
Advisor何时调用
代理创建出来了,那么我们的前置增强、后置增强、环绕增强等是如何在代理中体现的呢,对代理模式还不熟悉的同学一定要先看一下这篇文章呦:https://mp.weixin.qq.com/s/1DRmvuky5_NMRcH-toTLqQ
这里就简单看一下JDK动态代理的实现吧
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {MethodInvocation invocation;Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Object target = null;try {//equals方法处理if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {return equals(args[0]);}//hash代码处理else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {return hashCode();}else if (method.getDeclaringClass() == DecoratingProxy.class) {return AopProxyUtils.ultimateTargetClass(this.advised);}else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {// Service invocations on ProxyConfig with the proxy config...return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal;//如果配置内部方法调用的Advisorif (this.advised.exposeProxy) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// 获取当前方法的拦截器链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);if (chain.isEmpty()) {//如果没有拦截器直接调用切点方法Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);//执行拦截器链,重点,往下看retVal = invocation.proceed();}Class<?> returnType = method.getReturnType();//返回结果if (retVal != null && retVal == target &&returnType != Object.class && returnType.isInstance(proxy) &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {retVal = proxy;}else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);}return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {AopContext.setCurrentProxy(oldProxy);}}}
看完上方的代码,可以猜到,所有的Advisor都在这个拦截器里面了,那么这个拦截器又是如何实现的呢
public Object proceed() throws Throwable {// 执行完所有的Advisor后执行切点方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}//获取下一个要执行的拦截器Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// 递归调用// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.return proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}
至此SpringAOP的源码解析已经完成
