Spring AOP工作机制进一步理解(中篇)

来源:互联网 发布:淘宝代理商加盟可靠吗 编辑:程序博客网 时间:2024/06/05 08:32

       在Spring AOP工作机制进一步理解(上篇)中,通过源码,分析了<aop:config>配置下的Spring AOP工作机制,本文在总结上篇的基础上,分析<aop:aspectj-autoproxy>配置下的工作机制。

<aop:aspectj-autoproxy>

Spring xml配置文件

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd">  <!-- 用户业务逻辑bean --> <bean id="userAction" class="org.test.aop.UserAction"/>  <!-- 扫描日志切面bean --><context:component-scan base-package="org.test.aop"/>  <!-- 开启AOP注解方式 --><aop:aspectj-autoproxy/>  </beans>

解析

工作流程

        Spring xml的解析过程详见《Spring ioc容器启动流程—obtainFreshBeanFactory》,这里只涉及<aop:aspectj-autoproxy>的解析工作。AopNamespaceHandler会委托AspectJAutoProxyBeanDefinitionParser来进行解析工作,详细流程如下:


相关源码

/** AopConfigUtils.java */// 注册AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition// 其中cls的值为AnnotationAwareAspectJAutoProxyCreator.classprivate static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");// 判断是否已注册AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition// 其在beanFactory中对应的key为"org.springframework.aop.config.internalAutoProxyCreator"if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}// 创建且注册AnnotationAwareAspectJAutoProxyCreator RootBeanDefinitionRootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}/** AopNamespaceUtils.java */private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {if (sourceElement != null) {boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));// 获取<aop:aspectj-autoproxy/>的proxy-target-class属性值if (proxyTargetClass) {// 设置AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition的proxyTargetClass属性为trueAopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}// 获取<aop:aspectj-autoproxy/>的expose-proxy属性值boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));if (exposeProxy) {// 设置AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition的exposeProxy属性为trueAopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}/** AopConfigUtils.java */public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);}}static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);}}/** AopNamespaceUtils.java */private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) {if (beanDefinition != null) {BeanComponentDefinition componentDefinition =new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);parserContext.registerComponent(componentDefinition);}}/** AspectJAutoProxyBeanDefinitionParser.java */private void extendBeanDefinition(Element element, ParserContext parserContext) {BeanDefinition beanDef =parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);if (element.hasChildNodes()) {addIncludePatterns(element, parserContext, beanDef);}}

生成代理对象

         在<aop:aspectj-autoproxy/>解析过程中,主要工作就是注册AnnotationAwareAspectJAutoProxyCreator RootBeanDefinition。

AnnotationAwareAspectJAutoProxyCreator对象实例化

         与<aop:config>方式一样。

InstantiationModelAwarePointcutAdvisorImpl对象实例化

         <aop:aspectj-autoproxy/>配置下所有@Aspect中Advice注解最终都会实例为InstantiationModelAwarePointcutAdvisorImpl对象,以进行AOP拦截。与<aop:config>方式一样,在生成业务userAction代理对象过程中,InstantiationModelAwarePointcutAdvisorImpl的实例化发生在resolveBeforeInstantiation环节,与<aop:config>方式不同的是,AnnotationAwareAspectJAutoProxyCreator覆盖了AspectJAwareAdvisorAutoProxyCreator的findCandidateAdvisors方法,自行实例化注解的PointcutAdvisor。下面解析只涉及AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors,其他过程忽略。

AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors基本流程


相关源码

/** AnnotationAwareAspectJAutoProxyCreator.java */// <aop:aspectj-autoproxy/>注解方式下的PointcutAdvisor即InstantiationModelAwarePointcutAdvisorImpl对象实例化protected List<Advisor> findCandidateAdvisors() {// 实例化<aop:config>的AspectJPointcutAdvisorList<Advisor> advisors = super.findCandidateAdvisors();// 实例化<aop:aspectj-autoproxy/>的InstantiationModelAwarePointcutAdvisorImpladvisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());return advisors;}/** BeanFactoryAspectJAdvisorsBuilder.java */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及其循环上级的所有beanString[] beanNames =BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}// We must be careful not to instantiate beans eagerly as in this// case they would be cached by the Spring container but would not// have been weavedClass beanType = this.beanFactory.getType(beanName);if (beanType == null) {continue;}// 判断beanType及其循环super Class\interface是否带@Aspect// 采用(clazz.getAnnotation(annotationType)!= null)判断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);// 获取AdvisorsList<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);// 缓存classAdvisorsif (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;}// 从缓存中获取advisorsList<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;}/** ReflectiveAspectJAdvisorFactory */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)) {// 实例化<aop:aspectj-autoproxy/>注解方式下的PointcutAdvisor即InstantiationModelAwarePointcutAdvisorImplAdvisor 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;}// 获取aspectClass及其循环super Class\interface的不带@Pointcut的方法private List<Method> getAdvisorMethods(Class<?> aspectClass) {final List<Method> methods = new LinkedList<Method>();// 回调doWithReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {public void doWith(Method method) throws IllegalArgumentException {// 不包括pointcutsif (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {methods.add(method);}}});// 排序Collections.sort(methods, METHOD_COMPARATOR);return methods;}/** ReflectionUtils.java */public static void doWithMethods(Class<?> clazz, MethodCallback mc) throws IllegalArgumentException {doWithMethods(clazz, mc, null);}public static void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf)throws IllegalArgumentException {// 获取Declared MethodsMethod[] methods = clazz.getDeclaredMethods();for (Method method : methods) {if (mf != null && !mf.matches(method)) {continue;}try {mc.doWith(method);}catch (IllegalAccessException ex) {throw new IllegalStateException("Shouldn't be illegal to access method '" + method.getName()+ "': " + ex);}}if (clazz.getSuperclass() != null) {// 循环super ClassdoWithMethods(clazz.getSuperclass(), mc, mf);}else if (clazz.isInterface()) {for (Class<?> superIfc : clazz.getInterfaces()) {// 循环interfacedoWithMethods(superIfc, mc, mf);}}}/** ReflectiveAspectJAdvisorFactory.java */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;}// PointcutAdvisor对象实例化,<aop:aspectj-autoproxy/>注解方式下的PointcutAdvisorreturn new InstantiationModelAwarePointcutAdvisorImpl(this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);}// 获取candidateAdviceMethod的advice注解,提取Pointcut,返回AspectJExpressionPointcutprivate AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}AspectJExpressionPointcut ajexp =new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);ajexp.setExpression(aspectJAnnotation.getPointcutExpression());return ajexp;}/** AbstractAspectJAdvisorFactory.java */protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {//所有Advice注解Class<? extends Annotation>[] classesToLookFor = new Class[] {Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};// 循环查找匹配Advice的AspectJAnnotationfor (Class<? extends Annotation> c : classesToLookFor) {AspectJAnnotation foundAnnotation = findAnnotation(method, c);if (foundAnnotation != null) {return foundAnnotation;}}return null;}private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {A result = AnnotationUtils.findAnnotation(method, toLookFor);if (result != null) {// 获取到annotation则直接返回AspectJAnnotationreturn new AspectJAnnotation<A>(result);}else {return null;}}/** AnnotationUtils.java */public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {// 获取到annotation则直接返回A annotation = getAnnotation(method, annotationType);Class<?> clazz = method.getDeclaringClass();if (annotation == null) {// 在clazz的interface中查找带annotationType的methodannotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());}while (annotation == null) {// 在clazz的super Class中查找带annotationType的methodclazz = clazz.getSuperclass();if (clazz == null || clazz.equals(Object.class)) {break;}try {Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());annotation = getAnnotation(equivalentMethod, annotationType);}catch (NoSuchMethodException ex) {// No equivalent method found}if (annotation == null) {annotation = searchOnInterfaces(method, annotationType, clazz.getInterfaces());}}return annotation;}public static <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) {Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);// 利用Class.getAnnotation方法获取Annotation ClassA ann = resolvedMethod.getAnnotation(annotationType);if (ann == null) {for (Annotation metaAnn : resolvedMethod.getAnnotations()) {ann = metaAnn.annotationType().getAnnotation(annotationType);if (ann != null) {break;}}}return ann;}/** InstantiationModelAwarePointcutAdvisorImpl.java */// new 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 {// singleton aspect.// 实例化的Advicethis.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);// pointcut对象this.pointcut = declaredPointcut;this.lazy = false;}}// 实例化Adviceprivate Advice instantiateAdvice(AspectJExpressionPointcut pcut) {return this.atAspectJAdvisorFactory.getAdvice(this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);}/** ReflectiveAspectJAdvisorFactory.java */// 获取candidateAdviceMethod上的Advice对象public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {Class<?> candidateAspectClass = aif.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;// 根据Advice注解类型,实例化相应的Advice,用candidateAdviceMethod、ajexp、aif进行构造switch (aspectJAnnotation.getAnnotationType()) {case AtBefore: // @BeforespringAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);break;case AtAfter: // @AfterspringAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);break;case AtAfterReturning: // @AfterReturningspringAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}break;case AtAfterThrowing: // @AfterThrowingspringAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {springAdvice.setThrowingName(afterThrowingAnnotation.throwing());}break;case AtAround: // @AroundspringAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);break;case AtPointcut: // @Pointcutif (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;default:throw new UnsupportedOperationException("Unsupported advice type on method " + candidateAdviceMethod);}// 配置Advice对象springAdvice.setAspectName(aspectName);springAdvice.setDeclarationOrder(declarationOrderInAspect);String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {// 设置参数名称springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;}/** ReflectiveAspectJAdvisorFactory.java */// 获取@DeclareParents Annotation对象private Advisor getDeclareParentsAdvisor(Field introductionField) {DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);if (declareParents == null) {// Not an introduction fieldreturn null;}if (DeclareParents.class.equals(declareParents.defaultImpl())) {// This is what comes back if it wasn't set. This seems bizarre...// TODO this restriction possibly should be relaxedthrow new IllegalStateException("defaultImpl must be set on DeclareParents");}return new DeclareParentsAdvisor(introductionField.getType(), declareParents.value(), declareParents.defaultImpl());}

AnnotationAwareAspectJAutoProxyCreator生成代理类实例

          与<aop:config>方式一样。

调用代理对象

          与<aop:config>方式一样。

         <aop:aspectj-autoproxy/>与<aop:config>方式本质区别是PointcutAdvisor对象实例化方式不一样:<aop:aspectj-autoproxy/>采用注解方式,而<aop:config>则采用显示的xml配置方式,集中体现在findCandidateAdvisors。

0 0
原创粉丝点击