在讲解<aop>自定义标签时,提到了AspectJAwareAdvisorAutoProxyCreator的注册,对于AOP的实现基本就靠这个类实现。
AspectJAwareAdvisorAutoProxyCreator的层次结构如图所示,该类实现了BeanPostProcessor与SmartInstantiationAwareBeanPostProcessor这两个接口
ApplicationContext实现的默认行为就是会将所有的单例bean提前进行实例化,即会调用getBean(name),跟踪代码到AbstractAutowireCapableBeanFactory中createBean
此时 resolveBeforeInstantiation(beanName, mbd)就是给实现了SmartInstantiationAwareBeanPostProcessor接口的类的机会去改变bean
AbstractAutowireCapableBeanFactory
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args){
...
...
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
Object beanInstance = doCreateBean(beanName, mbd, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
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.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
如最上面的类层次结构图,此时会调用AbstractAutoProxyCreator中的postProcessBeforeInstantiation以及postProcessAfterInstantiation方法
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
throws BeansException {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
注意shouldSkip(beanClass, beanName),该方法其实已经找到所有的标有@AspectJ类中的增加方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.containsKey(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.put(beanName, Boolean.TRUE);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
AspectJAwareAdvisorAutoProxyCreator
@Override
protected boolean shouldSkip(Class beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
findCadidateAdvisors()即是寻找所有的增加方法,即标有@Before,@After,@AfterReturning,@Around等注解的方法,一个增强方法对应Advisor.
下面来看看findCadidateAdvisors()的逻辑
@Override
protected List<Advisor> findCandidateAdvisors() {
// 这个是寻找xml配置文件的advisors
List<Advisor> advisors = super.findCandidateAdvisors();
// 寻找标有注解的advisors,
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
如上所示,spring把寻找标有注解的advisor委托给了BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = null;
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
....
//获取所有注册的beanName
String[] beanNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
....
//判断beanType是否存在AspectJ注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
//AspectMetadata代表标有@AspectJ的类
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
....
//获取标记AspectJ注解中的增强方法
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
....
}
....
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
....
}
重点在this.advisorFactory.getAdvisors(factory)
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
final String aspectName = maaif.getAspectMetadata().getAspectName();
...
final List<Advisor> advisors = new LinkedList<Advisor>();
//getAdvisorMethods()寻找增强方法,即标有注解的方法不过排出了@Poincut
//并且是有序的集合,顺序分别是Around, Before, After, AfterReturning, AfterThrowing
//这也是5种通知在AOP中的拦截顺序
for (Method method : getAdvisorMethods(aspectClass)) {
//全部以InstantiationModelAwarePointcutAdvisorImpl返回
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
...
return advisors;
}
回到文章最开始,AspectJAwareAdvisorAutoProxyCreator实现了BeanPostProcessor接口,那么这个接口的方法在哪儿实现呢?答案在AbstractAutowireCapableBeanFactory类的initializeBean方法中,该方法调用applyBeanPostProcessorsAfterInitialization方法,即是BeanPostProcessor接口方法的调用之处
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
...
...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//BeanPostProcessor接口postProcessBeforeInitialization实现
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//initMethod方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//BeanPostProcessor接口postProcessAfterInitialization实现
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
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方法,该方法就是创建代理的地方了,匹配切点表达式的增强器就是getAdvicesAndAdvisorsForBean这个方法得来的
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
// Create proxy if we have advice.
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 List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
//该句代码在上面已做了分析
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//在candidateAdvisors中寻找匹配目标类的增加器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
跟踪findAdvisorsThatCanApply方法,其逻辑委托给了AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
...
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
...
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
当前循环的增强器是否匹配目标类是由canApply()方法判断的。放在编码阶段,就是目标类是否满足切点表达式,比如:execution(* com.uestc.test.aop.*.*(..)),即com.uestc.test.aop包下类的任何方法都应进行增强。
跟踪canApply方法,可以看到是通过MethodMatcher.match()方法来匹配的
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
其匹配过程大致是通过提取切入点表达式,根据切入点表达式来判断是否匹配,但是前面分析寻找增强方法时对于标有@Poincut注解的方法排除了,也没有看到切点表达式的提取。
我们来看看getClassFilter()
public ClassFilter getClassFilter() {
checkReadyToMatch();
return this;
}
对,切入点表达式的提取就在checkReadyToMacth()方法中
private void checkReadyToMatch() {
if (getExpression() == null) {
throw new IllegalStateException("Must set property 'expression' before attempting to match");
}
if (this.pointcutExpression == null) {
this.pointcutExpression = buildPointcutExpression();
}
}
buildPointCutExpression()即是提取切入点表达式,返回的类型是PointcutExpressionImpl,简单描述spring的做法就是通过反射来提取,但是spring的做法远比这复杂的多,这里暂不做分析。
由此,我们就找到了匹配目标类的增强器。