最是人间留不住,朱颜辞镜花辞树。这篇文章主要讲述AOP源码解析之二-创建AOP代理前传,获取AOP信息。相关的知识,希望能为你提供帮助。
AOP源码解析之二-创建AOP代理前传,获取AOP信息。
上篇文章对AOP的基本概念说清楚了,那么接下来的AOP还剩下两个大的步骤获取定义的AOP信息,生成代理对象扔到beanFactory中。
本篇文章重点对前半部分,如何获取到AOP信息的过程解读。
在Spring的核心方法Refresh方法中,aop是在
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
开始切入的,该文章就开始深入这个方法进行解析。
@Nullable
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.
// hasInstantiationAwareBeanPostProcessors()是来判断容器中是否有InstantiationAwareBeanPostProcessor的实现bean
// AOP切面后置处理器AspectJAwareAdvisorAutoProxyCreator就实现了InstantiationAwareBeanPostProcessor接口
if (!mbd.isSynthetic() &
&
hasInstantiationAwareBeanPostProcessors())
Class<
?>
targetType = determineTargetType(beanName, mbd);
if (targetType != null)
// 执行实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor中的前置处理方法postProcessBeforeInstantiation方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null)
// 执行实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor中的后置处理方法postProcessAfterInitialization方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
mbd.beforeInstantiationResolved = (bean != null);
return bean;
见名知意,resolveBeforeInstantiation(执行初始化前方法),这一步主要判断一下工厂中是否有 InstantiationAwareBeanPostProcessor 的实现bean。InstantiationAwareBeanPostProcessor 应该是AOP最核心的接口了。
我们看一下InstantiationAwareBeanPostProcessor 的继承结构。
文章图片
我们详细的说下InstantiationAwareBeanPostProcessor 这个接口。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor Object postProcessBeforeInstantiation(Class<
?>
beanClass, String beanName) throws BeansException;
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
它和 BeanPostProcessor 的方法非常相似,而且它还继承了 BeanPostProcessor。
下面是 BeanPostProcessor 中的两个方法:
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
发现没有,InstantiationAwareBeanPostProcessor 是
Instantiation
,BeanPostProcessor 是 Initialization
,它代表的是 bean 在实例化完成并且属性注入完成,在执行 init-method 的前后进行作用的。而 InstantiationAwareBeanPostProcessor 的执行时机要前面一些,我们回到refresh方法的doCreateBean中看一下。
文章图片
看到这读者想必对于aop的执行时机已经模模糊糊的心里有个大概了。
我们定义的环绕通知,创建代理一定是在postProcessBeforeInitialization完成的。
我们的重点就是看看postProcessBeforeInitialization的方法中的通知怎么获取,怎么创建代理对象的进行详细的解读。
本文先对前半部分解读。
我们继续看postProcessBeforeInitialization有哪些实现类。
文章图片
我们重点看AbstractAutoProxyCreator的实现类。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName)
if (bean != null)
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 1.判断当前bean是否需要被代理,如果需要则进行封装
if (this.earlyProxyReferences.remove(cacheKey) != bean)
//1.判断当前bean是否需要被代理,如果需要则进行封装
return wrapIfNecessary(bean, beanName, cacheKey);
return bean;
如果需要代理执行继wrapIfNecessary方法。
//这个方法将返回代理类
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey)
// 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
if (StringUtils.hasLength(beanName) &
&
this.targetSourcedBeans.contains(beanName))
return bean;
// 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey)))
return bean;
// 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName))
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
// Create proxy if we have advice.
// 4.获取当前bean的Advices和Advisors
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 5.如果存在增强器则创建代理
if (specificInterceptors != DO_NOT_PROXY)
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理...创建代理...创建代理...
// 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),
// 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 5.2 创建完代理后,将cacheKey ->
代理类的class放到缓存
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
// 6.标记为无需处理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
4.1 我们先查看第一条主线,获取当前bean的Advices和Advisors
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<
?>
beanClass, String beanName, @Nullable TargetSource targetSource) // 1.找到符合条件的Advisor
List<
Advisor>
advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty())
// 2.如果没有符合条件的Advisor,则返回null
return DO_NOT_PROXY;
return advisors.toArray();
注:Advisors即是aop的环绕通知。
protected List<
Advisor>
findEligibleAdvisors(Class<
?>
beanClass, String beanName)
// 1.查找所有的候选Advisor
List<
Advisor>
candidateAdvisors = findCandidateAdvisors();
// 2.从所有候选的Advisor中找出符合条件的
List<
Advisor>
eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 3.扩展方法,留个子类实现
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty())
// 4.对符合条件的Advisor进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
return eligibleAdvisors;
这一步所做的事很简单,就是查找所有候选的Advisor,但是调用链路特别的长,如果将这些彻底搞明白,还是需要耗费一番功夫的,读者可以选择深入程度。
1、寻找可用的Advisor
public List<
Advisor>
findAdvisorBeans()
// Determine list of advisor bean names, if not cached already.
// 1.确认advisor的beanName列表,优先从缓存中拿
String[] 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!
//1.1 如果缓存为空,则获取class类型为Advisor的所有bean名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
if (advisorNames.length == 0)
return new ArrayList<
>
();
// 2.遍历处理advisorNames
List<
Advisor>
advisors = new ArrayList<
>
();
for (String name : advisorNames)
if (isEligibleBean(name))
// 2.1 跳过当前正在创建的advisor
if (this.beanFactory.isCurrentlyInCreation(name))
if (logger.isTraceEnabled())
logger.trace("Skipping currently created advisor " + name + "");
else
try
// 2.2 通过beanName获取对应的bean对象,并添加到advisors
advisors.add(this.beanFactory.getBean(name, Advisor.class));
catch (BeanCreationException ex)
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException)
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null &
&
this.beanFactory.isCurrentlyInCreation(bceBeanName))
if (logger.isTraceEnabled())
logger.trace("Skipping advisor " + name +
" with dependency on currently created bean: " + ex.getMessage());
// Ignore: indicates a reference back to the bean were trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
throw ex;
// 3.返回符合条件的advisor列表
return advisors;
/**
* 找到符合条件的Advisor
* @return
*/
@Override
protected List<
Advisor>
findCandidateAdvisors()
// Add all the Spring advisors found according to superclass rules.
List<
Advisor>
advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null)
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
public List<
Advisor>
buildAspectJAdvisors()
List<
String>
aspectNames = this.aspectBeanNames;
// 1.如果aspectNames为空,则进行解析
if (aspectNames == null)
synchronized (this)
aspectNames = this.aspectBeanNames;
if (aspectNames == null)
List<
Advisor>
advisors = new ArrayList<
>
();
aspectNames = new ArrayList<
>
();
// 1.1 获取所有的beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 1.2 循环遍历所有的beanName,找出对应的增强方法
for (String beanName : beanNames)
// 1.3 不合法的beanName则跳过,默认返回true,子类可以覆盖实现,AnnotationAwareAspectJAutoProxyCreator
// 实现了自己的逻辑,支持使用includePatterns进行筛选
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 weaved.
// 获取beanName对应的bean的类型
Class<
?>
beanType = this.beanFactory.getType(beanName);
if (beanType == null)
continue;
// 1.4 如果beanType存在Aspect注解则进行处理
if (this.advisorFactory.isAspect(beanType))
// 将存在Aspect注解的beanName添加到aspectNames列表
aspectNames.add(beanName);
// 新建切面元数据
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON)
// 使用BeanFactory和beanName创建一个BeanFactoryAspectInstanceFactory,主要用来创建切面对象实例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 1.5 解析标记AspectJ注解中的增强方法*********************
List<
Advisor>
classAdvisors = this.advisorFactory.getAdvisors(factory);
// 1.6 放到缓存中
if (this.beanFactory.isSingleton(beanName))
// 如果beanName是单例则直接将解析的增强方法放到缓存
this.advisorsCache.put(beanName, classAdvisors);
else
// 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法
this.aspectFactoryCache.put(beanName, factory);
// 1.7 将解析的增强器添加到advisors
advisors.addAll(classAdvisors);
else
// Per target or per this.
if (this.beanFactory.isSingleton(beanName))
// 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常
throw new IllegalArgumentException("Bean with name " + beanName +
" is a singleton, but aspect instantiation model is not singleton");
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
// 将factory放到缓存,之后可以通过factory来解析增强方法
this.aspectFactoryCache.put(beanName, factory);
// 解析标记AspectJ注解中的增强方法,并添加到advisors中
advisors.addAll(this.advisorFactory.getAdvisors(factory));
// 1.9 将解析出来的切面beanName放到缓存aspectBeanNames
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));
// 1.10 最后返回解析出来的增强器
return advisors;
@Override
public List<
Advisor>
getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory)
// 1.前面我们将beanClass和beanName封装成了aspectInstanceFactory的AspectMetadata属性,
// 这边可以通过AspectMetadata属性重新获取到当前处理的切面类
Class<
?>
aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 2.获取当前处理的切面类的名字
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 3.校验切面类
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
// 4.使用装饰器包装MetadataAwareAspectInstanceFactory,以便它只实例化一次。
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<
Advisor>
advisors = new ArrayList<
>
();
// 5.获取切面类中的方法(也就是我们用来进行逻辑增强的方法,被@Around、@After等注解修饰的方法,使用@Pointcut的方法不处理)
for (Method method : getAdvisorMethods(aspectClass))
// 6.处理method,获取增强器
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null)
// 7.如果增强器不为空,则添加到advisors
advisors.add(advisor);
// If its a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() &
&
lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated())
// 8.如果寻找的增强器不为空而且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
// Find introduction fields.
// 9.获取DeclareParents注解
for (Field field : aspectClass.getDeclaredFields())
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null)
advisors.add(advisor);
return advisors;
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) // 1.校验切面类
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 2.AspectJ切点信息的获取(例如:表达式),就是指定注解的表达式信息的获取,
// 如:@Around("execution(* com.joonwhee.open.aop.*.*(..))")
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 3.如果expressionPointcut为null,则直接返回null
if (expressionPointcut == null)
return null;
// 4.根据切点信息生成增强器
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
获取到@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut定义注解信息
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<
?>
candidateAspectClass)
// 1.查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)
// 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解
AspectJAnnotation<
?>
aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
// 2.如果方法没有使用AspectJ的注解,则返回null
if (aspectJAnnotation == null)
return null;
// 3.使用AspectJExpressionPointcut实例封装获取的信息
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<
?>
[0]);
// 提取得到的注解中的表达式,
// 例如:@Around("execution(* com.joonwhee.open.aop.*.*(..))"),得到:execution(* com.joonwhee.open.aop.*.*(..))
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null)
ajexp.setBeanFactory(this.beanFactory);
return ajexp;
@Nullable
protected static AspectJAnnotation<
?>
findAspectJAnnotationOnMethod(Method method)
// 设置要查找的注解类
for (Class<
?>
clazz : ASPECTJ_ANNOTATION_CLASSES)
// 查找方法上是否存在当前遍历的注解,如果有则返回
AspectJAnnotation<
?>
foundAnnotation = findAnnotation(method, (Class<
Annotation>
) clazz);
if (foundAnnotation != null)
return foundAnnotation;
return null;
2、获取切点以后就需要生成增强器了。
new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName)
/**
* 根据切点信息生成增强器
* @param declaredPointcut
* @param aspectJAdviceMethod
* @param aspectJAdvisorFactory
* @param aspectInstanceFactory
* @param declarationOrder
* @param aspectName
*/
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) // 1.简单的将信息封装在类的实例中
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
// aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
// 2.是否需要延迟实例化
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated())
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If its 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, aspectInstanceFactory);
this.lazy = true;
else
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 3.实例化增强器:根据注解中的信息初始化对应的增强器
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
【AOP源码解析之二-创建AOP代理前传,获取AOP信息。】经过以上长长的源码分析过程,就将aop的第一个大过程,获取到我们定义的@Before、@After的方法以后,进行增强,下一步就要拿到这些获取的信息去创建代理对象了。
推荐阅读
- 50行代码实现《汇编语言》王爽 实验七
- 好久没有更新了,这次给大家带来的是linux中的用户配额和组配额。还有一个重要的事情给我投投票呗嘻嘻!
- MySql数据库增删改查常用语句命令
- 代码实现 加性注意力 | additive attention #51CTO博主之星评选#
- #yyds干货盘点#安装悟空CRM
- Docker基本管理
- Java桥接方法
- prometheus基于文件服务发现
- Ansible配置文件命令及模块