Spring源码分析二:AOP篇

Spring源码分析二:AOP篇,第1张

文章目录
  • (一)spring Aop概念
  • (二)Spring Aop简单使用
    • (1)创建Aop切面
    • (2)创建被拦截的Bean
    • (3)XML配置文件定义bean
    • (4)测试用例
  • (三)Aop原理分析
    • 1、Spring支持Aop的前提条件
    • 2、Aop环境的初始化
      • (1)处理internalAutoProxyCreator类型的BeanDefinition
      • (2)处理proxy-target-class和expose-proxy属性
      • (3)注册新生成的BeanDefinition到容器监听器
    • 3、AOP代理结构
    • (1)获取增强方法
      • (1)获取所有的增强器findCandidateAdvisors
      • (2)寻找匹配的代理增强器
    • (2)创建代理

(一)spring Aop概念

spring aop简称面向切面编程,不同于OOP即面向对象编程,OOP作为开发业务时,如需要引入安全检测、系统日志、监控等功能时,每个对象都需要引入公共代码,会造成不可维护和冗余代码,AOP的横空出世,正是为了解决OOP纵向的继承关系,AOP关心的是横向切面关系,在某一时刻进行切入,执行一些额外的逻辑。

本文不对较低的sprig aop版本进行分析,直接从spring支持@AspectJ开始进行分析,该注解中主要是在切面中定义一个切点和切入点即可。

(二)Spring Aop简单使用

使用Aop两种方式,一种是注解方式,另一种是XML配置文件,本次采用最基础的XMl方式去创建AOP;

(1)创建Aop切面
 public class TestAop {

     @Pointcut("execution(* com.spring.service.PlayerService.player(int))&&args(number)")
     public void pointCut(int number){}

     @Before(value = "pointCut(number)")
     public void before(int number){
         System.out.println("TestAop is before! " + number);
     }

     @After(value = "pointCut(number)")
     public void after(int number){
         System.out.println("TestAop is after! " + number);
     }

     @AfterReturning(value = "pointCut(number)")
     public void afterReturning(int number){
         System.out.println("TestAop is afterReturning! " + number);
     }

     @AfterThrowing(value = "pointCut(number)")
     public void afterThrowing(int number){
         System.out.println("TestAop is afterThrowing! " + number);
     }

     @Around(value = "pointCut(number)")
     public void around(ProceedingJoinPoint joinPoint,int number) throws Throwable {
         joinPoint.proceed();
         System.out.println("TestAop is around! "+number);
     }
 }
(2)创建被拦截的Bean
 public interface PlayerService {
     void player(int number);
 }

 public class PlayerServiceImpl implements PlayerService {

     @Override
     public void player(int number) {
         System.out.println("Player WuBai: "+number);
     }
 }
(3)XML配置文件定义bean
 <?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd" default-autowire="byName">

      <aop:aspectj-autoproxy />
      <bean id = "playerService" class="com.spring.service.PlayerServiceImpl"></bean>
      <bean class="com.spring.aop.TestAop"/>
  </beans>
(4)测试用例
  public class Test1 {
      public static void main(String[] args) {
          ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/applicationContext.xml");
          PlayerService players = applicationContext.getBean("playerService", PlayerService.class);
          players.player(3);
      }
  }

输出如下:

TestAop is before! 3
Player WuBai: 3
TestAop is around! 3
TestAop is after! 3
TestAop is afterReturning! 3

(三)Aop原理分析

Spring Aop发挥作用,前提是要开启对aop的支持,开启方式用两种,XMl配置文件开启方式:,
注解开启方式:在基于注解的容器配置类添加@EnableAspectJAutoProxy即可,上述两种方式均可开启Spring对Aop的支持,
本文分析方式原理,两种方式相差不大,原理基本相同,只是部分细节处理不同。

1、Spring支持Aop的前提条件

Spring 在容器启动时,首先会去解析配置文件或者配置注解,解析配置文件为BeanDefinition时伴随着解析, 在Spring源码分析一:容器篇中第二步加载容器时,里面有解析BeanDefinition时,就有调用支持aop的处理,处理过程如下:
obtainFreshBeanFactory()->refreshBeanFactory()->loadBeanDefinitions(beanFactory)->loadBeanDefinitions(beanDefinitionReader) -> reader.loadBeanDefinitions(configResources)->loadBeanDefinitions(resource)->loadBeanDefinitions(new EncodedResource(resource)) ->doLoadBeanDefinitions(inputSource, encodedResource.getResource())->registerBeanDefinitions(doc, resource) ->documentReader.registerBeanDefinitions(doc, createReaderContext(resource))->doRegisterBeanDefinitions(doc.getDocumentElement()) ->(解析核心方法)parseBeanDefinitions(root, this.delegate)

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				if (delegate.isDefaultNamespace(ele)) {
					parseDefaultElement(ele, delegate);
				}
				else {
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		delegate.parseCustomElement(root);
	}
}

上述解析spring默认标签或者用户自定义标签时会调用下面parseCustomElement方法,里面就是aop开始发挥作用的地方,
NamespaceHandlerResolver中定义的resolve方法,返回的类型为NamespaceHandler,实际上是通过AopNamespaceHandler子类去实例化完成;

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    String namespaceUri = getNamespaceURI(ele);
    if (namespaceUri == null) {
        return null;
    }
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

DefaultNamespaceHandlerResolver中定义了resolve,其中核心点为namespaceHandler.init()方法,此步是spring支持Aop的关键

public NamespaceHandler resolve(String namespaceUri) {
      Map<String, Object> handlerMappings = getHandlerMappings();
      Object handlerOrClassName = handlerMappings.get(namespaceUri);
      if (handlerOrClassName == null) {
          return null;
      }
      else if (handlerOrClassName instanceof NamespaceHandler) {
          return (NamespaceHandler) handlerOrClassName;
      }
      else {
          String className = (String) handlerOrClassName;
          try {
              Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
              if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                  throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                          "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
              }
              NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
              namespaceHandler.init();//支持aop的前提条件
              handlerMappings.put(namespaceUri, namespaceHandler);
              return namespaceHandler;
          }
          catch (ClassNotFoundException ex) {
              throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
                      "] for namespace [" + namespaceUri + "]", ex);
          }
          catch (LinkageError err) {
              throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
                      className + "] for namespace [" + namespaceUri + "]", err);
          }
      }
  }
2、Aop环境的初始化

在第一步中提到了Aop在何时开始进行调用AOP环境,init()中可直观的看到对aspectj-autoproxy的注册,使用AspectJAutoProxyBeanDefinitionParser作为AOP的默认解析器,代码如下:

 public void init() {
	registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
	registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
	registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
	registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}

在Spring中所有的BeanDefinition解析器基本都是从parse出发,AOP解析器也一样,里面主要是registerAspectJAnnotationAutoProxyCreatorIfNecessary方法发挥作用:

public BeanDefinition parse(Element element, ParserContext parserContext) {
    //注册AnnotationAwareAspectJAutoProxyCreator
	AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
	//处理被继承的子类
	extendBeanDefinition(element, parserContext);
	return null;
}

注册AnnotationAwareAspectJAutoProxyCreator的关键核心点:

(1)处理org.springframework.aop.config.internalAutoProxyCreator类型的BeanDefinition;
(2)处理proxy-target-class和expose-proxy;
(3)将(1)生成的beanDefinition注册到容器监听器中。

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
	//处理org.springframework.aop.config.internalAutoProxyCreator类型的BeanDefinition
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    //处理proxy-target-class和expose-proxy
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    //将该方法中第一步生成的beanDefinition注册到容器的监听器中
    registerComponentIfNecessary(beanDefinition, parserContext);
}
(1)处理internalAutoProxyCreator类型的BeanDefinition

主要是由AnnotationAwareAspectJAutoProxyCreator类来支持,根据@PointCut定义切点,切点中定义了匹配bean的语法,用于创建代理对象,由AnnotationAwareAspectJAutoProxyCreator来实现该功能:

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

主要判断是否采用了用户在XML中配置的org.springframework.aop.config.internalAutoProxyCreator类型的bean代理器,如果存在则需要进行优先级的判定并根虎优先级采用那个类型作为BeanDefinition的class类型

private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    //判断是否自定义了自动代理器,如定义,则需要进行优先级判断先使用那个
    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());//改变BeanDefinition中的class类型
            }
        }
        return null;
    }
    RootBeanDefinition 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;
}
(2)处理proxy-target-class和expose-proxy属性

XML配置文件中是否存在PROXY_TARGET_CLASS_ATTRIBUTE和EXPOSE_PROXY_ATTRIBUTE的配置,存在则进行自动代理

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
    if (sourceElement != null) {
        boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        if (proxyTargetClass) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        if (exposeProxy) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

强制使用了AUTO_PROXY_CREATOR_BEAN_NAME类型即org.springframework.aop.config.internalAutoProxyCreator类来
处理proxy-target-class和expose-proxy两个属性

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);
    }
}
public 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);
    }
}

proxy-target-class属性决定了采用基于接口的JDK动态代理,还是基于字节码文件的cglib代理,两者的区别为前者是对被代理的目标对象是否有实现接口,如果实现了接口,那么对于这种对象是使用JDK动态代理来生成,如果目标对象没有实现任何接口,则默认采用cglib代理生成目标对象。

强制使用cglib只需要在配置文件中配置proxy-target-即可,缺陷是无法通知final修饰符所修饰的方法,cglib包需要放在classpath下。

代理模式类型:

JDK动态代理:被代理的目标对象必须是某个接口的实现类,在运行期间创建接口的实现类来完成对目标对象的代理;
cglib代理:在运行期间生成目标对象的代理对象,针对目标扩展类的子类,cglib底层依赖ASM即字节码编辑类库, *** 作字节码实现,性能比JDK代理强。

expose-proxy属性:主要是解决目标对象自身内部调用导致无法增强的问题如类中一个方法a调用自身类中的方法b,两个方法都加了事务,自身this.b()会导致其失效,配置该属性为true时,再将this.b()换为((T)AopContext.currentProxy).b()即可。

(3)注册新生成的BeanDefinition到容器监听器
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
	if (beanDefinition != null) {
		parserContext.registerComponent(
				new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
	}
}
3、AOP代理结构

AnnotationAwareAspectJAutoProxyCreator类层次结构如下:
AnnotationAwareAspectJAutoProxyCreator是在AOP初始化环境中被注册进去,即在Spring加载过程中,注册时会执行其间接父类AbstractAutoProxyCreator中的postProcessAfterInitialization方法,因AnnotationAwareAspectJAutoProxyCreator中间接继承的类中实现了BeanPostProcessor后置处理器,在Spring加载时会执行后置处理器,该执行逻辑,自行查看Spring源码分析一——容器篇中有详细介绍。
AbstractAutoProxyCreator–>postProcessAfterInitialization方法如下:

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        //基于className或beanName创建一个key,可能是&+beanName,也可能是className
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        //earlyProxyReferences是一个并发map,主要是存储需要被代理bean
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            //核心方法wrapIfNecessary,对bean进行封装并代理
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;//该处表明bean为null或已经被代理过
}

根据beanClass和beanName来确定key的生成,同时判断是否为BeanFactory类型,此类型则返回key为&+beanName。

protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
    if (StringUtils.hasLength(beanName)) {
        return (FactoryBean.class.isAssignableFrom(beanClass) ?
                BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
    }else{
        return beanClass;
    }
}

spring是否真正创建代理需要进行一系列判断,是否被处理过,是否不需要被代理等,最终获取增强方法和创建代理,否则使用一些辅助类变量进行缓存如targetSourcedBeans、advisedBeans、proxyTypes作为是否代理bean的辅助缓存。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   //是否已经被spring处理过,targetSourcedBeans集合Set存储
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
       return bean;
   }
   //利用advisedBeans并发map集合存储,直接过滤不需要处理的bean
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
       return bean;
   }
   //基础设施类不被代理和特殊配置bean不被代理的进行记录,使用advisedBeans并发集合存储
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
       this.advisedBeans.put(cacheKey, Boolean.FALSE);
       return 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;
   }
   //执行到此处代表上述逻辑都不符合,则表明该bean不需要被代理
   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}

wrapIfNecessary方法中如果该bean符合被代理的条件,则会进行两个核心步骤,分别为获取增强方法和创建代理。

(1)获取增强方法

wrapIfNecessary中的getAdvicesAndAdvisorsForBean方法是委托给子类AbstractAdvisorAutoProxyCreator去进行实现,主要就是获取Advisor增强方法,代码如下:

protected Object[] getAdvicesAndAdvisorsForBean(
		Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
	//获取所有的Advisor增强方法
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}

findEligibleAdvisors主要是做了两个事情:
1)找寻所有的增强器;
2)寻找匹配的代理增强器。

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;
	}
(1)获取所有的增强器findCandidateAdvisors

获取增强器,是由AnnotationAwareAspectJAutoProxyCreator类实现,先调用父类AbstractAdvisorAutoProxyCreator中的findCandidateAdvisors方法获取配置文件XML中的aop声明,自身的注解aop声明交由buildAspectJAdvisors方法去实现,如下:

protected List<Advisor> findCandidateAdvisors() {
     //调用父类在配置文件中的aop声明
     List<Advisor> advisors = super.findCandidateAdvisors();
     // Build Advisors for all AspectJ aspects in the bean factory.
     if (this.aspectJAdvisorsBuilder != null) {
         //获取自身注解定义的aop声明,并合并到配置文件中声明的AOP中
         advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
     }
     return advisors;
 }

buildAspectJAdvisors方法是AOP注解中的核心方法,其主要思想分为以下步骤:

1)获取spring容器中的所有bean;
2)遍历bean,找到被AspectJ注解的类;
3)对标记了AspectJ注解的类进行增强器提取;
4)将提取结果缓存到变量中,便于使用。

代码如下:

public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = this.aspectBeanNames;//获取被AspectJ注解类的beanName
	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;//加锁重新获取,保证加锁过程中是最新的数据
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				//从容器中获取所有的beanName
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					if (!isEligibleBean(beanName)) {//默认返回的true,自定义扩展可更改
						continue;
					}
					//获取bean的class类型
					Class<?> beanType = this.beanFactory.getType(beanName);
					if (beanType == null) {
						continue;
					}
					//提取被AspectJ注解过的类
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);//将其添加到aspectNames中,遍历完时重新赋值给aspectBeanNames
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							MetadataAwareAspectInstanceFactory factory =
									new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							//解析被AspectJ注解的增强方法,getAdvisors方法是提取的核心方法,详细请查看[Spring源码番外篇-AOP补充一](http://t.csdn.cn/0wxaC)
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							if (this.beanFactory.isSingleton(beanName)) {
								this.advisorsCache.put(beanName, classAdvisors);//单例缓存存储
							}else {
								this.aspectFactoryCache.put(beanName, factory);//原型作用域的bean存储
							}
							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);//bean作用域为原型的存储
							advisors.addAll(this.advisorFactory.getAdvisors(factory));
						}
					}
				}
				this.aspectBeanNames = aspectNames;
				return advisors;
			}
		}
	}

	if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}
	//将增强方法缓存
	List<Advisor> advisors = new ArrayList<>();
	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;
}
(2)寻找匹配的代理增强器

该步骤其实就是在(1)中获取到的所有增强器与Point中的表达式进行结合,满足于我们在spring中定义的具体业务方法进行应用。具体表现在findAdvisorsThatCanApply方法中,代码如下:

protected List<Advisor> findAdvisorsThatCanApply(
             List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
     ProxyCreationContext.setCurrentProxiedBeanName(beanName);
     try {
         //在获取到的所有增强器中来过滤不是该表达式匹配的增强方法
         return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
     }finally {
         ProxyCreationContext.setCurrentProxiedBeanName(null);
     }
 }

findAdvisorsThatCanApply方法主要用于过滤不是对应bean业务的表达式增强器,canApply方法是真正过滤的关键点,分两步处理,第一步是先处理IntroductionAdvisor这种类型的增强器,第二步是处理普通类型的增强器,canApply方法因本文篇幅受限,请查看spring源码分析番外篇——AOP补充一

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	for (Advisor candidate : candidateAdvisors) {//开始遍历过滤
	    //第一步先处理IntroductionAdvisor增强器即支持用户自定义实现IntroductionAdvisor,进行个性化开发
		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;
}
(2)创建代理

未完待续。。。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/738496.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存