Spring事务管理(3)-AOP创建Advisors
来源:互联网 发布:ubuntu maven m2 编辑:程序博客网 时间:2024/06/05 14:14
在上一篇文章中,详细讲述了Spring中注册AOP解析器的过程。在这篇文章中,将进一步讲解Advisors的创建过程。
Spring中注册AOP解析器的所有操作都是针对AnnotationAwareAspectJAutoProxyCreator进行的。AnnotationAwareAspectJAutoProxyCreator是实现AOP的根本。首先观察AnnotationAwareAspectJAutoProxyCreator的类层次结构。
图1 AnnotationAwareAspectJAutoProxyCreator的类层次结构
从上图中可以看到,AnnotationAwareAspectJAutoProxyCreator继承AspectJAwareAdvisorAutoProxyCreator类,实现BeanPostProcessor接口。其中AspectJAwareAdvisorAutoProxyCreator是完成xml配置的代理创建。 我们知道,当一个类实现了BeanPostProcessor接口,那么在Spring在生成bean时会在实例化完成前调用postProcessAfterInitialization方法。
通过查看AnnotationAwareAspectJAutoProxyCreator的父类,在AbstractAutoProxyCreator中找到了postProcessAfterInitialization方法。
/*** Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.containsKey(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean;}
在上述方法中,wrapIfNecessary对所有bean实例进行增强处理。其中最重要的逻辑是获得Advisors以及创建代理对象。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 如果bean已经处理,则从缓存中返回已经处理的bean if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) { return bean; } // 如果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; } // 获得bean的增强方法 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;}
进一步跟进getAdvicesAndAdvisorsForBean函数。
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;}
- 寻找所有的增强方法candidateAdvisors
findCandidateAdvisors方法包含多个实现方式,AnnotationAwareAspectJAutoProxyCreator的实现中包括寻找xml中配置的增强以及解析所有注解方法的增强。
protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 调用AbstractAdvisorAutoProxyCreator的findCandidateAdvisors // findCandidateAdvisors方法会寻找xml中配置的增强方法。 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. // 添加所有注解方式的增强 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors;}
1.1 寻找xml中配置的增强
此处寻找比较简单,由于xml在配置文件解析阶段以及生成bean,因此只要去beanFactory中获得所有的Advisor的的bean即可。
protected List<Advisor> findCandidateAdvisors() { // advisorRetrievalHelpers是BeanFactoryAdvisorRetrievalHelper的对象 // 用来检索所有增强方法return this.advisorRetrievalHelper.findAdvisorBeans();}
public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! // 此处查找所有的名称,但不进行初始化 // 如果此处进行初始化,遇到需要增强的bean时,会进入死循环 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { // 从beanFactory中获得增强advisor,并添加到返回结果中 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { … throw ex; } } } } return advisors;}
1.2 查找带Aspect注解的增强
回到findCandidateAdvisors方法中,语句this.aspectJAdvisorsBuilder.buildAspectJAdvisors()寻找注解形式的增强器。
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>(); // 从beanFactory中查找所有bean,包括父类中的bean // 递归查找String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } Class beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 判断是否包含Aspect注解 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); // 创建AspectMetadata对象 // 在该对象中将通过beanTypep判断AspectJ的实例化模型 // AspectMetadata amd = new AspectMetadata(beanType, beanName); // 如果是Singleton实例化模型 // singleton实例化模型表示切面只会有一个实例 if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { //创建MetadataAwareAspectInstanceFactory 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; }
以上代码看上去比较长,但其实流程相对清晰。首先查找Spring中所有的beanName,然后判断下该 bean是否带Aspect注解,如果存在注解,则获得该bean中的所有增强。
值得注意的是,在生成AspectMetadata时,会获得Aspect注解类的实例化模型。所谓实例化模型是指何时实例化切面。Spring AOP支持AspectJ的singleton、perthis、pertarget、pertypewithin实例化模型(目前不支持percflow、percflowbelow)。
singleton:切面只会有一个实例
perthis: 每个切入点表达式匹配的连接点对应的AOP对象都会创建一个新切面实例
pertarget: 每个切入点表达式匹配的连接点对象的目标对象都会创建一个新的切面实例
perwithin:
回到以上方法的this.advisorFactory.getAdvisors(factory),该语句返回所有的增强器。
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) { 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 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;}
在生成所有Advisor的方法中,重点是寻找所有增强方法,并返回增强实例。其中getAdvisorMethods将方法所有增强方法。在这个方法中,将寻找aspectClass中所有的方法,并添加到集合中返回。
private List<Method> getAdvisorMethods(Class<?> aspectClass) { final List<Method> methods = new LinkedList<Method>(); ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {public void doWith(Method method) throws IllegalArgumentException { // Exclude pointcuts if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { methods.add(method); } } }); Collections.sort(methods, METHOD_COMPARATOR); return methods;}
在上面的函数中,我们获得了aspectClass中的所有方法,接下来将根据方法生成Advisor对象了。
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);}
可以看到Advisor最终返回的是InstantiationModelAwarePointcutAdvisorImpl对象。该对象包含了切点信息以及实例化的avdice(如果是singleton切面类型)。此处省略部分逻辑代码,在获得advice的函数中,包含如下逻辑。可以看到,不同的注解对象将返回不同的切面类型。
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); }
归纳下寻找注解中的增强器的过程,首先查找Spring管理的所有bean,然后判断bean是否带有Aspect注解,如果存在,则进一步查找该bean中的所有增强方法,根据配置的@Before等注解生成不同的advisors。
- 寻找合适的增强方法findAdvisorsThatCanApply
该过程相对简单,寻找class合适的增强。即通过pointcut注解进行判断即可。
- Spring事务管理(3)-AOP创建Advisors
- Spring事务管理(4)-AOP创建代理
- spring事务管理,AOP模式
- spring aop事务管理配置
- Spring Aop事务管理
- Spring AOP 事务管理
- spring aop事务管理
- spring aop xml事务管理
- spring aop 事务管理
- Spring事务管理、Aop
- Spring之Advisors
- Spring事务管理——AOP注解事务管理
- spring事务管理AOP (mini show)
- Spring事务管理-aop切入配置
- 【spring】中的事务管理AOP配置.
- Spring事务管理—AOP/Annotation
- Spring的AOP和事务管理机制概览
- Spring的AOP和事务管理机制概览
- java中equals和==的区别
- 入门题集(持续更新)
- 数据库连接池、读取properties配置文件小结
- 李欣老师视频笔记,只记录自己可能会忘的基础Efficient java
- Codeforces Round #363 (Div. 2), problem: (B)
- Spring事务管理(3)-AOP创建Advisors
- 系统编程(文件操作续)--C语言学习(3)
- 重定向和转发
- android 模拟表单文件上传servlet
- error C2065: 'IDD_DIALOG1' : undeclared identifier
- 一种适合服务器运行程序保护的思路
- The specified child already has a parent. You must call removeView() on the child's parent first.
- 主题模型及其变种的实现代码汇总
- 编译链接的基本步骤