上文讲了spring是如何开启AOP的,简单点说就是将AnnotationAwareAspectJAutoProxyCreator这个类注册到容器中,由于这个类最终实现了BeanPostProcessor接口,并且在其postProcessAfterInitialization()方法中完成了AOP代理对象的建立,建立时机则是在bean的init方法被执行以后即bean初始化完成以后。postProcessAfterInitialization()方法是重点,本文及下一篇文章都是围绕着这个方法来的。html
该方法是实如今其父类中的AbstractAutoProxyCreator,咱们先来看一下其实现:spring
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { // 根据给定的bean的class和name构件key,格式:beanClassName_beanName Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.containsKey(cacheKey)) { // 若是它适合被代理,则在这里面生成代理类 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 若是已经处理过则再也不处理 if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) { return bean; } // 无需加强则直接返回 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 指定的bean类是否表明一个基础设施类,基础设施类不该被代理,或者配置了指定bean也不须要自动代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 若是存在Advice则建立代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 若是获取到了加强则须要针对加强建立代理 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; }
在上面的函数中咱们已经能够看到代理建立的雏形,固然,在真正开始以前还须要通过一系列判断,好比是否已经处理过或者是不是须要跳过的bean,而真正建立代理是从getAdvicesAndAdvisorsForBean开始的。
建立代理主要包含了两个步骤:express
这里虽然看起来只有简单的两步,可是每一步中都有着大量复杂的逻辑。本文先来看看获取加强方法的实现逻辑。缓存
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) { List advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
对于某个bean的加强方法的获取也是包含两个步骤的,获取全部的加强以及寻找全部加强中适用于bean的加强并应用,而findCandidateAdvisors()与findAdvisorsThatCanApply()即是作了这两件事情。这里若是没法找到对应的加强器则直接返回DO_NOT_PROXY,也就是null。app
这里咱们分析的是注解方式的AOP,对于findCandidateAdvisors的实现实际上是由AnnotationAwareAspectJAutoProxyCreator类来完成的,继续跟踪:ide
protected List<Advisor> findCandidateAdvisors() { // 使用注解方式配置AOP的时候并不会丢弃对XML配置的支持,在这里会调用父类方法去加载配置文件中的AOP声明 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAdvisorAutoProxyCreator,在实现获取加强的方法中除了保留父类的获取配置文件中定义的加强外,同时增长了获取Bean的注解加强的功能,这部分实现是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()来完成的。函数
这里其实能够本身先尝试想象一下解析思路,看看本身的实现与Spring是否有差异?咱们能够先在本身头脑中尝试实现一下获取加强这个功能点,看看是否有思路。实际上,Spring在实现的时候主要分红了四步:post
咱们来看看Spring如何实现对全部的类进行分析并提取Advisor:学习
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = null; synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); // 获取全部的beanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); // 遍历全部的beanName找出对应的加强方法 for (String beanName : beanNames) { // 不合法的bean则略过,由子类定义规则,默认返回true if (!isEligibleBean(beanName)) { continue; } // 获取对应的bean的类型 Class beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 若是该bean上存在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); // 解析加强方法 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 { // Per target or per this. 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.EMPTY_LIST; } // 记录缓存 List<Advisor> advisors = new LinkedList<Advisor>(); 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的提取,在上面步骤中最为重要也最为复杂的就是加强器的获取,这一功能是委托给getAdvisors方法来实现(this.advisorFactory.getAdvisors(factory))。 ui
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) { // 获取标记为AspectJ的类及其名字,并验证 final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass(); final String aspectName = maaif.getAspectMetadata().getAspectName(); validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(maaif); final List<Advisor> advisors = new LinkedList<Advisor>(); for (Method method : getAdvisorMethods(aspectClass)) { // 获取加强器 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; }
上面函数中首先完成了对加强器的获取,包括获取注解以及根据注解生成加强的步骤,而后考虑到在配置中可能会将加强配置成延迟初始化,那么须要在首位加入同步实例化加强器以保证加强使用以前的实例化,最后是对DeclareParents注解的获取,这里着重分析对加强器的获取。
对普通加强器的获取逻辑是实如今getAdvisor方法中的,实现步骤包括对切点的注解的获取以及根据注解信息生成加强。
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { validate(aif.getAspectMetadata().getAspectClass()); // 切点信息的获取 AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass()); if (ajexp == null) { return null; } // 根据切点信息生成加强器 return new InstantiationModelAwarePointcutAdvisorImpl( this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName); }
所谓获取切点信息就是指定注解的表达式信息的获取,如@Before("test()")。
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { // 获取方法上的注解 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // 使用AspectJExpressionPointcut实例封装获取的信息 AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]); // 提取获得的注解中的表达式,如: // @Pointcut("execution(* *.*test*(..))")中的execution(* *.*test*(..))") ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); return ajexp; } protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) { // 设置敏感的注解类 Class<? extends Annotation>[] classesToLookFor = new Class[] { Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class}; for (Class<? extends Annotation> c : classesToLookFor) { AspectJAnnotation foundAnnotation = findAnnotation(method, c); if (foundAnnotation != null) { return foundAnnotation; } } return null; } // 获取指定方法上的注解并使用AspectJAnnotation封装 private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) { A result = AnnotationUtils.findAnnotation(method, toLookFor); if (result != null) { return new AspectJAnnotation<A>(result); } else { return null; } }
全部的加强都是由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl统一封装的。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp, MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) { this.declaredPointcut = ajexp; this.method = method; this.atAspectJAdvisorFactory = af; this.aspectInstanceFactory = aif; this.declarationOrder = declarationOrderInAspect; this.aspectName = aspectName; if (aif.getAspectMetadata().isLazilyInstantiated()) { // Static part of the pointcut is a lazy type. Pointcut preInstantiationPointcut = Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. // If it's not a dynamic pointcut, it may be optimized out // by the Spring AOP infrastructure after the first evaluation. this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif); this.lazy = true; } else { // A singleton aspect. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); this.pointcut = declaredPointcut; this.lazy = false; } }
在封装过程当中只是简单地将信息封装在类的实例中,全部的信息单纯地赋值,在实例初始化的过程当中还完成了对于加强器的初始化。由于不一样的加强所体现的逻辑是不一样的,好比@Before("test()")与@After("test()")标签的区别就是加强器加强的位置不一样,因此就须要不一样的加强器来完成不一样的逻辑,而根据注解中的信息初始化对应的加强器就是在instantiateAdvice函数中实现的。
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { return this.atAspectJAdvisorFactory.getAdvice( this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); } public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); 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 class 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; // 根据不一样的注解类型封装不一样的加强器 switch (aspectJAnnotation.getAnnotationType()) { case AtBefore: springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif); break; case AtAfter: springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif); break; case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; case AtAround: springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif); break; case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; default: throw new UnsupportedOperationException( "Unsupported advice type on method " + candidateAdviceMethod); } // Now to configure the advice... springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrderInAspect); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
从上面能够看到,Spring会根据不一样的注解生成不一样的加强器,例如AtBefore会对应AspectJMethodBeforeAdvice,在AspectJMethodBeforeAdvice中完成了加强方法的逻辑。本文尝试分析几个经常使用的加强器实现。
这是前置加强器,在Spring中,它会封装到MethodBeforeAdviceInterceptor类的内部,这个是一个拦截器,会被放在拦截器链中,在建立代理bean时会用到:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } }
其中的属性MethodBeforeAdvicce就表明着前置加强的AspectJMethodBeforeAdvice,跟踪其before()方法:
public void before(Method method, Object[] args, Object target) throws Throwable { invokeAdviceMethod(getJoinPointMatch(), null, null); } protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable { return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex)); } protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable { Object[] actualArgs = args; if (this.aspectJAdviceMethod.getParameterTypes().length == 0) { actualArgs = null; } try { ReflectionUtils.makeAccessible(this.aspectJAdviceMethod); // 激活加强方法 return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs); } catch (IllegalArgumentException ex) { throw new AopInvocationException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; pointcut expression [" + this.pointcut.getPointcutExpression() + "]", ex); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } }
invokeAdviceMethodWithGivenArgs方法中的aspectJAdviceMethod正是对应于前置加强的方法,在这里实现了调用。
后置加强与前置加强有稍许不一致的地方。回顾上面讲过的前置加强,大体的结构是在拦截器链中放置MethodBeforeAdviceInterceptor,并在MethodBeforeAdviceInterceptor中又放置了AspectJMethodBeforeAdvice,在调用inovke时首先串联调用。可是在后置加强的时候倒是不同的,没有提供如MethodBeforeAdviceInterceptor的中间类,而是直接实现MethodInterceptor接口,并在拦截器链中使用了中间的AspectAfterAdvice。
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice { public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { // 激活加强方法 invokeAdviceMethod(getJoinPointMatch(), null, null); } } }
前面已经把全部加强器的获取分析完了,可是对于全部加强来讲,并不必定都适用于当前的Bean,还要挑选出适合的加强器,也就是知足咱们配置的通配符的加强器。这部分的具体实如今findAdvisorsThatCanApply中。
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { // 过滤已经获得的advisors 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) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
findAdvisorsThatCanApply函数的主要功能是寻找全部加强器中适用于当前class的加强器,而对于真正的匹配实际上是在canApply中实现的。
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 { // It doesn't have a pointcut so we assume it applies. 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(); 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 = clazz.getMethods(); for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
这里的逻辑也不是很复杂,无非就是根据advisor中封装的classFilter来判断是否match对应的类。
本文主要学习了Spring AOP核心实现原理中的对加强方法的获取,主要包含两个步骤:
下文会聚焦在AOP核心实现原理的另外一部分--代理的建立。