回首Spring源码之AOP:解析切面(aspect)
前言之前分析了spring容器创建bean的整个流程,其中涉及到了bean的后置处理器的几处调用,其中在bean的实例化前置调用中,aop会在此处解析aspect切面,我们先来回顾一下这个BeanPostProcessor。解析切面//bean后置处理器实例化前置处理Object bean = resolveBeforeInstantiation(beanName, mbdToUse);prote
前言
之前分析了spring容器创建bean的整个流程,其中涉及到了bean的后置处理器的几处调用,其中在bean的实例化前置调用中,aop会在此处解析aspect切面,我们先来回顾一下这个BeanPostProcessor。
解析切面
//bean后置处理器实例化前置处理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//循环调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
在上篇讲到的@EnableAspectjAutoProxy中引入的bean实现了InstantiationAwareBeanPostProcessor ,下面来到AbstractAutoProxyCreator#postProcessBeforeInstantiation:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//首先时获取缓存,类似这种缓存在送spring中广泛使用
Object cacheKey = getCacheKey(beanClass, beanName);
//这里的targetSourcedBeans也是一个缓存,缓存了通过customTargetSourceCreators创建了代理的bean
//customTargetSourceCreators是留给开发者的一个扩展点,用以指定bean代理的目标对象
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
//表示之前已经判断过了,跳过
return null;
}
最重要的方法shouldSkip,在这里解析切面
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
//表示这个bean不需要被代理,跳过
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//下面这个if:如果指定了CustomTargetSource,那么提前为bean创建代理,创建代理的过程和aop一样,只是targetSource换成了指定的CustomTargetSource
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
下面进入shouldSkip方法解析切面:
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
//findCandidateAdvisors找到容器中所有Advisor,并且实例化
//Advisor在aop中为通知类,其中包括了adivce通知和pointcut切点
//aspect类中的每个通知方法都会被解析成一个Advisor
//AnnotationAwareAspectJAutoProxyCreator这个bean会在这里解析切面
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
//调用父类的shouldSkip
return super.shouldSkip(beanClass, beanName);
}
protected List<Advisor> findCandidateAdvisors() {
//调用父类findCandidateAdvisors拿到容器中所有的Advisor
//一般为空,引入声明式事务的话会有相应的Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
//aspectJAdvisorsBuilder.buildAspectJAdvisors()解析切面
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
下面进入解析aspect切面的过程:
public List<Advisor> buildAspectJAdvisors() {
//这里又是缓存
List<String> aspectNames = this.aspectBeanNames;
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) {
//isEligibleBean总返回true
if (!isEligibleBean(beanName)) {
continue;
}
//拿到bean的class类型
Class<?> beanType = this.beanFactory.getType(beanName, false);
if (beanType == null) {
continue;
}
//判断类上是否有aspectj注解
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 {
// 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.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
//下面这个循环将解析出来的Advisor加入返回的集合advisors
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;
}
真正解析切面的 this.advisorFactory.getAdvisors(factory):
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//拿到切面类class,就是打了aspect注解的对象
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//切面名称
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
//对aspectInstanceFactory进行装饰,可以理解为一个静态代理,代理了aspectInstanceFactory的getAspectInstance方法
//代理了aspectInstanceFactory的getAspectInstance方法,它会直接调用getBean获取bean对象
//这里lazySingletonAspectInstanceFactory是new出来的对象
//对于同一个lazySingletonAspectInstanceFactory对象没必要创建多次AspectInstance,
//所以在lazySingletonAspectInstanceFactory对这方法代理,缓存了AspectInstance实例对象
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//getAdvisorMethods(aspectClass)会拿到除了@Pointcut注解的方法外的所有方法
for (Method method : getAdvisorMethods(aspectClass)) {
//将通知方法解析为一个Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
//这里对不是单例的aspect处理,几乎不用
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
//aop中的introduction,也几乎不用,不去了解
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
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;
}
// 将切点表达式、 和通知 封装到InstantiationModelAwarePointcutAdvisorImpl对象中
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
//获取切点的方法
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//获取方法上的通知注解,@Around @Before @After @AfterReturning @AfterThrowing
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//用通知注解构建AspectJExpressionPointcut切点
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
//设置切点表达式Expression
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
再看一下通知器对象的构造方法:
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//当前的切点
this.declaredPointcut = declaredPointcut;
//切面的class对象
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
//切面方法的名称
this.methodName = aspectJAdviceMethod.getName();
//切面方法的参数类型
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
//切面方法对象
this.aspectJAdviceMethod = aspectJAdviceMethod;
//aspectj的通知工厂
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
//aspect的实例工厂
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;
//把切面中的通知构造为一个一个的advice通知对象
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
对于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;
//根据注解类型,创建对应的advice
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround://环绕通知
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
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;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
//配置一下advice
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
这5种通知后面会转换成MethodInterceptor方法拦截器,aop调用时执行invoke方法进行拦截,其中AspectJAroundAdvice,AspectJAfterAdvice,AspectJAfterThrowingAdvice直接实现了MethodInterceptor,而AspectJMethodBeforeAdvice,AspectJAfterReturningAdvice由于不是MethodInterceptor的实现类需要通过适配器转换成MethodInterceptor,后续在aop创建代理的时候详细介绍。
总结
当spirng创建第一个bean的时候,所有Advicor就会在bean实例化前置调用处解析,也就是只会解析一次,然后缓存起来,以后就不会进去了。解析切面相当于aop的准备工作,后续将会详细分析aop创建代理和方法拦截的过程。
更多推荐
所有评论(0)