spring AOP 注解原理

缘起

我们知道,其实AOP是一种编程思想——面向切面. 即程序运行期间动态的将某段代码切入到指定位置进行运行的编程方式. 典型的用法可以参见【1】. 其实非java config的用法在之前使用xml的时候都大同小异的使用过. 但是本文就想从源码的角度分析Sping-AOP是如何实现的

分析

注册bean定义

首先,纵观【1】,我们发现最值得怀疑的分析入手点就是 MainConfig上的注解@EnableAspectJAutoProxy了. 我们看看此注解干了什么

1
2
3
...
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

而Spring提供的 @Import注解的作用就是导入 AspectJAutoProxyRegistrar 到bean中去.

而我们看看AspectJAutoProxyRegistrar 这个类

1
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

而ImportBeanDefinitionRegistrar接口的作用就是它的registerBeanDefinitions方法. 这个方法的作用就是手动注入bean. 我们看看其源码

1
2
3
...
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
...

这个registerAspectJAnnotationAutoProxyCreatorIfNecessary的中文硬译就是 注册一个AspectJAnnotationAutoProxyCreator,如果需要的话. 但是按照【1】中的场景,显然就是需要, 不是吗? 所以我们有理由跟进去,不是吗? 随意跟进两步,我们看到了如下源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { // AUTO_PROXY_CREATOR_BEAN_NAME=org.springframework.aop.config.internalAutoProxyCreator
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;
}
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;
}

​ 源码1

debug发现,上面的cls入参就是AnnotationAwareAspectJAutoProxyCreator. registry是DefaultListableBeanFactory(BeanDefinitionRegistry接口的一个实现类,从名字就能看出,registry用于bean定义信息的注册),用于我们注册bean定义的东西.

上面代码的逻辑是先判断是否已经注册了id为org.springframework.aop.config.internalAutoProxyCreator(下简称internalAutoProxyCreator)的bean的话,则就做一些操作,我们目前是首入,所以这个判断条件不成立的. 所以我们来到了上面第18行代码. 最后返回的是 beanDefinition。哦,对,忘了说了,此调用栈的出发点自然是ioc容器启动的refresh方法(AbstractApplicationContext的). 而且是refresh方法中的

1
2
// Invoke factory processors registered as beans in the context. 调用 BeanFactoryPostProcessors来注册bean的定义信息
invokeBeanFactoryPostProcessors(beanFactory);

​ 源码2

查阅Spring 4.3.12-RELEASE 官方文档,BeanFactoryPostProcessors和BeanPostProcessor 接口不同,前者用于Customizing configuration metadata with a BeanFactoryPostProcessor. 其原文如下

1
2
3
4
5
6
The next extension point that we will look at is
the org.springframework.beans.factory.config.BeanFactoryPostProcessor. The
semantics of this interface are similar to those of the BeanPostProcessor, with one major difference:
BeanFactoryPostProcessor operates on the bean configuration metadata; that is, the Spring IoC
container allows a BeanFactoryPostProcessor to read the configuration metadata and potentially
change it before the container instantiates any beans other than BeanFactoryPostProcessors.

上面说的很明白了,BeanFactoryPostProcessors就是用于读取bean的定义的(只是定义,譬如长下面这个样子

1
Root bean: class [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null

). 而在【2】中,我们已经分析过BeanPostProcessor的作用了,就是初始化bean之后,再干点儿什么. 所以不难想象,BeanPostProcessor的处理一定在源码2之后. 证据还是在refresh方法中

1
2
3
4
5
6
7
8
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
...
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

​ 源码3

上面第一条是注册bean的定义(你看,源码1返回的不就是beanDefinition么?)第二条是注册BeanPostProcessors(bean的后置处理器), 这些后置处理器的作用(正如【2】中所说)是拦截bean的初始化过程的. 第三条就是初始化bean. 期间会被第二条注册好的bean后置处理器进行拦截.

这是ioc初始化bean的基本过程. 即bean的定义在先. 要改bean的定义要在这里改.

好了,扯皮了一会儿. 回到源码1. 我们关注第18行代码,其中beanDefinition是AnnotationAwareAspectJAutoProxyCreator的bean的定义. 所以我们将AnnotationAwareAspectJAutoProxyCreator的bean的定义信息注册为了名(id)为internalAutoProxyCreator的bean. 则源码1结束,我们就向ioc容器中注册了一个这样的bean(自动代理创建器)定义信息.

ps: 这里顺便说一句源码1的第18行代码, 它做的事情是(其实在【3】中已经说过了)

org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(String, BeanDefinition)

1
2
3
...
this.beanDefinitionNames.add(beanName); // beanDefinitionNames就是注册到ioc容器中的bean定义,beanDefinitionNames的官方注释就是List of bean definition names, in registration order
...

所以注册bean的定义信息其实就是往DefaultListableBeanFactory的beanDefinitionNames中添加beanName即可.

so, 这就完了? of course NOT!!!

AnnotationAwareAspectJAutoProxyCreator

从上一小节,我们知道ioc容器中已经有了一个AnnotationAwareAspectJAutoProxyCreator的bean的定义信息.

ps: 其实,这里多说一句,其实springboot、springcloud或者spring本身有很多的 @EnableXXX 注解,一般的套路就是引入了某个bean,然后你要去研究这个bean,这个bean的功能研究透了, 整个原理就搞清楚了.

回到正题,ioc容器中已经有了一个这样的bean的定义信息,不用说我们也知道,肯定是要初始化这个bean的,不然引入他的定义干什么? 难道引入着好玩? 那么这个类长什么样子呢?

1
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

然后一路狂点其父类,发现了我们感兴趣的东西

1
2
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

所以AnnotationAwareAspectJAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor(一个 BeanPostProcessor接口的子接口)以及BeanFactoryAware接口. 这里需要注意的是,SmartInstantiationAwareBeanPostProcessor接口虽然是BeanPostProcessor的子接口,但是我们关心的接口方法并不是BeanPostProcessor的postProcessBeforeInitialization、postProcessAfterInitialization,而是postProcessBeforeInstantiation、postProcessAfterInstantiation,即把Initialization换成了Instantiation.

而且我们知道,既然AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,所以是一定会在源码3中的第二步进行注册的.

现在我们来捋一下AnnotationAwareAspectJAutoProxyCreator中我们需要关心的方法. 显然就是setBeanFactory方法和上面说到的postProcessBeforeInstantiation、postProcessAfterInstantiation方法. 而这个在其父类AbstractAdvisorAutoProxyCreator中.

1
2
3
4
5
6
7
8
9
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

​ 源码4

其中initBeanFactory(源码4的第八行)调用的是AnnotationAwareAspectJAutoProxyCreator自己的. 源码如下

1
2
3
4
5
6
7
8
9
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}

​ 源码5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);

if (beanName == null || !this.targetSourcedBeans.contains(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.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;
}

​ 源码6

postProcessAfterInstantiation只是简单地返回true.

所以综上所述,我们只需要分析清楚AnnotationAwareAspectJAutoProxyCreator作为bean后置处理器做了哪些工作,作为BeanFactoryAware做了哪些工作,这些分析清楚了,AOP的原理就基本清楚了.

registerBeanPostProcessors(注册bean后置处理器)的过程(以AnnotationAwareAspectJAutoProxyCreator为例)

注意源码3中的第二步, 我们一直强调说源码3的第一步用于注册bean的定义信息(往BeanDefinitionRegistry中注册),并没有初始化bean. 例如,我们已经往BeanDefinitionRegistry中注册了AnnotationAwareAspectJAutoProxyCreator的定义信息(它是一个BeanPostProcessor). 但是这些BeanPostProcessor 是在源码3的第二步被初始化的. 那么它是怎么初始化的呢? 我们跟一下源码就会找到

org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext) 方法, 里面第一步就是

1
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

​ 源码7

表示获取已经注册的BeanPostProcessor类型的bean的定义信息. 不仅仅包含我们之前已经注册的AnnotationAwareAspectJAutoProxyCreator的定义信息,还有其他一些spring自带的BeanPostProcessor. 而且这里还会增加一些别的BeanPostProcessor

1
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

​ 源码8

之后做的事情就是Separate between BeanPostProcessors that implement PriorityOrdered, Ordered, and the rest. 即将这些BeanPostProcessors 中实现了PriorityOrdered接口(Ordered的子接口)的放一起,实现了Ordered接口的放一起,剩下的没有实现Ordered接口的放一起. 最后将PriorityOrdered排序,Ordered排序,最后将这三部分又都加入到internalPostProcessors中去. 即在最后的internalPostProcessors中,实现了PriorityOrdered的排在最前,其次是实现了Ordered接口的,最后就是没实现Ordered接口的. 而且我们感兴趣的AnnotationAwareAspectJAutoProxyCreator实现了Ordered接口. 回到正题——在源码3的第二步我们是要初始化这些Bean后置处理器呢! 所以我们必须要初始化这个bean. 怎么初始化的呢? 依旧是在此方法(PostProcessorRegistrationDelegate.registerBeanPostProcessors)中

1
2
3
4
5
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
...
// First, register the BeanPostProcessors that implement PriorityOrdered.
// Next, register the BeanPostProcessors that implement Ordered.
registerBeanPostProcessors(beanFactory, orderedPostProcessors); // 真正的注册orderedPostProcessors(我们可爱的AnnotationAwareAspectJAutoProxyCreator就实现了Ordered接口,所以会被加入到orderedPostProcessors中去)

​ 源码9

这里ppName=org.springframework.aop.config.internalAutoProxyCreator

然后跟下去, getBean–>doGetBean, 然后来到了如下源码(org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String, Class, Object[], boolean)中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args); // 这里才是真正的创建bean(mbd是bean 定义信息)
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

​ 源码10

你看,这里会走第4行, 则跳到如下源码

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory<?>)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
...
if (newSingleton) {
addSingleton(beanName, singletonObject);
}

​ 源码11

注意第21行. 因为这是第一次进入此代码,所以第4行获取到的一定是null, 则就会走第21行. 而singletonFactory是源码10中的传入的ObjectFactory,所以第21行会回调源码10中的第五行代码(这是典型的回调啊), 但是源码10中的第7行代码就是createBean了, 也就是既然不存在,我就创建,然后源码11中的第26行就将其加入到singletonObjects中去,以便下次再来的时候就源码11的第5行就不再是null了(这样保证了单实例,即创建好的bean都会被缓存起来). 所以我们要继续跟进源码10的第七行代码. createBean–>doCreateBean(注意,之前是getBean–>doGetBean, 现在因为拿不到,改成创建了) 最后来到 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[]).

1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}

​ 源码12

注释本身就是 “初始化bean实例”. 而源码12的第2行的代码中的bean已经存在了. 所以这里bean是创建,而源码12是对创建的bean进行初始化(populateBean就是干这种事情的,即给bean的各种属性进行赋值)。 而bean的创建代码在源码12的上方一点

1
2
3
4
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);

​ 源码13

mbd是bean的定义信息.beanName就是org.springframework.aop.config.internalAutoProxyCreator——这个我们要在源码3的第二步初始化的bean. 现在我们回到源码12的第6行,此时已经创建(源码13)、赋属性值(源码12第四行)完毕了, 现在要做的事情就是initializeBean(其实这就是ioc生成bean的过程,并不仅仅针对bean后置处理器,bean都是

先注册定义信息->然后创建->赋属性值(populateBean)->initializeBean(后置处理器干活)),

这个initializeBean其实特别重要,因为我们的bean后置处理器其实就是在这里面干活的. 所以我们跟进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
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()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}

​ 源码14

这里可以看到initializeBean工作的流程. 值得注意的是第12行,invokeAwareMethods方法. 跟进去此方法

1
2
3
4
5
6
7
8
9
10
11
12
13
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

​ 源码15

即如果bean实现了xxxaware接口的话,就会在这里调用相应接口的方法. 因为我们的AnnotationAwareAspectJAutoProxyCreator实现了BeanFactoryAware接口,所以会进入源码15的第10行代码

我们先不着急进入,先看看如果源码14中invokeAwareMethods方法执行完毕之后会干什么. 我们注意到了一个wrappedBean,以及在【2】中就指出的一段源码(这就是BeanPostProcessor 接口的原理)

1
2
3
4
5
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); // 拿出所有后置处理器跑一边执行其postProcessorsBeforeInitialization方法
...
invokeInitMethods(beanName, wrappedBean, mbd); // 执行自定义的init方法.或者PostConstruct方法
...
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);// 拿出所有后置处理器跑一边执行其postProcessorsAfterInitialization方法

​ 源码16

所以后置处理器+initMethod方法其实是在xxxAware接口处理之后进行的.

源码16的第一行就是应用后置处理器(BeanPostProcessor). 它的源码是

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}

​ 源码17

我们可以很清晰的看到,applyBeanPostProcessorsBeforeInitialization方法其实就是拿出所有的后置处理器来跑一边(具体参见【2】). 但是对于AnnotationAwareAspectJAutoProxyCreator而言,目前存在的后置bean处理器全部是spring自带的(一共7个

1
[org.springframework.context.support.ApplicationContextAwareProcessor@7f0eb4b4, org.springframework.context.support.ApplicationListenerDetector@19bb089b, org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@5c33f1a9, org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker@1623b78d, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@3ce1e309, org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@6aba2b86, org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor@158da8e]

),所以任何bean创建的流程(即上面提到的initializeBean方法)都是

xxxAware–>跑后置处理器的postbeforeinitialization方法–>invokeInitMethods(执行InitializingBean接口的afterPropertiesSet方法)–>跑后置处理器的postafterinitializationx方法.

经过这么漫长的梳理,我们回到源码15的第10行代码, 因为我们要继续讨论以下话题

作为BeanFactoryAware

源码15的第10行代码将进入源码4, 而源码4第三行将简单的调用

1
this.beanFactory = beanFactory;

将beanFactory注入进来, 然后我们来到源码4的第八行. 则再跟进,就来到了

源码5 AnnotationAwareAspectJAutoProxyCreator自己的initBeanFactory方法. 而源码5中做的事情就是创建了aspectJAdvisorsBuilder和aspectJAdvisorFactory. 至此,AnnotationAwareAspectJAutoProxyCreator已经创建完毕,最后我们回到源码9,其最后一行就完成了AnnotationAwareAspectJAutoProxyCreator这个bean后置处理器的注册. 其实所谓的注册就是

1
2
3
4
5
6
7
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor); // 其实就是将postProcessor加入到org.springframework.beans.factory.support.AbstractBeanFactory.beanPostProcessors(一个ArrayList)
}
}

​ 源码18

至此,我们以AnnotationAwareAspectJAutoProxyCreator为例,演示了注册BeanPostProcessor的全过程. 至此,ioc中已经存在了AnnotationAwareAspectJAutoProxyCreator这个bean后置处理器. (最早只是注册此bean的定义). 下面,只要创建bean,就会被AnnotationAwareAspectJAutoProxyCreator这个bean后置处理器拦截,看看能不能增强(从而完成AOP功能). 这是下面的话题

AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor

至此,我们已经完成了AnnotationAwareAspectJAutoProxyCreator的注册定义+创建的全过程. 下面我们看看这个bean后置处理器将起到什么作用. 回顾之前讲解的initializeBean的过程,现在的AnnotationAwareAspectJAutoProxyCreator已经能参与到任何bean的初始化过程了. 首先,我们的出发点是

源码3中的第三条了,即初始化其他单实例bean. 然后进入到finishBeanFactoryInitialization中的如下源码

1
2
3
...
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

继而进入到preInstantiateSingletons方法中的

1
2
3
4
5
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
...
getBean(beanName);
}

目的都是完成剩下的单实例bean(之所以说剩下的是因为前面我们已经初始化了一些单实例bean,例如一些BeanPostProcessor)而这里的beanNames即beanDefinitionNames 在【3】中讲了. 后面就和上面AnnotationAwareAspectJAutoProxyCreator的创建过程一模一样了(就是getBean–>doGetBean 你搜一下”getBean–>doGetBean”前面就知道了). 只是会被AnnotationAwareAspectJAutoProxyCreator拦截. 所以我们在初始化 mathCaculator 的时候,会来到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)方法,

等一下!!!! are you kidding me ?

之前不是说好的postProcessBeforeInitialization么(之前说了创建bean的过程中是跑后置处理器的postbeforeinitialization方法)? 怎么现在变成了postProcessBeforeInstantiation了?

不要急,我们看看进入到源码12之前干了什么?

我们来到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])

1
2
3
4
5
6
7
8
9
10
11
12
13
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 这里希望后置处理器能返回一个代理对象,mbdToUse是类的定义信息
if (bean != null) { // 如果能返回一个代理对象
return bean; // 就返回
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 如果第五行不能返回一个代理对象,则走上面AnnotationAwareAspectJAutoProxyCreator的老路,即源码12
Object beanInstance = doCreateBean(beanName, mbdToUse, args); // 这一行就会进入到源码12

​ 源码19

调用栈显示,我们在上面第三行进入的postProcessBeforeInstantiation方法, 其实我们也可以看到作者已经给出的注释——Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 即这里给一个机会让直接返回代理,注意第5行的return,而不会再到后面跑postbeforeinitialization方法之后才返回了. 所以这里相当于是拦截了一道.

所以我们可以得到如下结论

1
AnnotationAwareAspectJAutoProxyCreator 的作用是可以在真正创建bean(即上面的createBean,你搜一下getBean-->doGetBean就看到了)之前拦截一道,尝试看看能不能为其创建代理返回,如果可以就直接返回了,如果不行,才真正创建bean对象进行注册. 所以对于能生成代理的,ioc容器中存在的根本不是类本身,而是代理.

所以我们的注意力就集中到了源码19的第三行, 即下面的话题

创建代理对象

继续跟 源码 19 的第三行,我们可以进入到如下源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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); // 先before试一下
if (bean != null) { // before失败,after就不会再试了
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean; // before 和after都返回null,最终才返回null
}

​ 源码25

1
2
3
4
5
6
7
8
9
10
11
12
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
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;
}

即遍历所有的后置处理器,如果是 InstantiationAwareBeanPostProcessor 类型的, 则调用其 postProcessBeforeInstantiation 接口方法.而我们之前的AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor恰好就是这种类型的. 所以我们来到了如下源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);

if (beanName == null || !this.targetSourcedBeans.contains(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.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;
}

​ 源码20

第三行得到bean的名字,beanClass是com.yfs.bean.MathCaculator(即需要增强的bean),第六行中advisedBeans 是

1
{org.springframework.context.event.internalEventListenerFactory=false, mainConfig=false, org.springframework.context.event.internalEventListenerProcessor=false}

里面是false表明这些bean不需要被增强. 如果cacheKey在这个advisedBeans中的话,显然就不需要增强,就返回null了,则一旦返回null, 增强失败就会老老实实创建bean了(即源码19 的第四行判断). 然后来到第九行,首先判断isInfrastructureClass

1
2
3
4
5
6
7
8
9
10
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
源码21

以及(这是子类AnnotationAwareAspectJAutoProxyCreator的实现,实际运行因为现在是AnnotationAwareAspectJAutoProxyCreator,所以一定走的是源码22,只是源码22中有super的调用,所以也会走源码21)

1
2
3
4
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
}

​ 源码22

即问com.yfs.bean.MathCaculator是不是Advice、Pointcut、Advisor、AopInfrastructureBean这些基础class. 以及是不是切面,源码22中的isAspect源码如下

1
2
3
4
5
6
7
8
@Override
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

​ 源码23

可见就是使用AnnotationUtils看看有没有@Aspect注解. 所以切面类也不需要增强的.

如果是的话,则也不需要增强, 并且将这种不需要增强缓存 进 advisedBeans. 再判断是否需要跳过,即shouldSkip(也是AnnotationAwareAspectJAutoProxyCreator的实现)

1
2
3
4
5
6
7
8
9
10
11
12
13
@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);
}

​ 源码24

第四行获取到增强器(即advisor),什么叫做增强器? 就是我们写在切面LogAspects 中的四个方法, 所以candidateAdvisors 中有4个增强器. 这里遍历这四个增强器做判断,如果是AspectJPointcutAdvisor类型的增强器的话,就可能认定需要跳过. 而我们目前每个增强器的类型是InstantiationModelAwarePointcutAdvisor,不是AspectJPointcutAdvisor类型的. 所以上面的遍历都是false的. 而super对shouldSkip 的实现异常简单,就是返回false. 所以源码24返回的就是false.所以回到源码20,能够来到第18行. beanName是mathCaculator,而源码20的targetSource依旧是null,则源码20返回null. 即源码25 中的 postProcessBeforeInstantiation返回null了,所以我们根据源码25的思路就不会尝试postProcessAfterInstantiation,(此时其实我是有点失落的~ 难道不应该在源码19 的第五行解决战斗吗? )则会进入到源码19的第13行老老实实创建bean(doCreateBean), 而doCreateBean的过程中就会调用 AnnotationAwareAspectJAutoProxyCreator的 postProcessBeforeInstantiation、postProcessAfterInitialization方法(其实是调用它的父类AbstractAutoProxyCreator的这两个方法). 而postProcessBeforeInitialization是平凡的

1
2
3
4
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}

所以我们注意力集中在postProcessAfterInitialization,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

​ 源码26

注释也写得很明白——此方法的目的是创建代理对象返回. 注意,上面源码26的bean已经不是null了(因为已经创建并赋属性值了甚至aware接口也处理完毕了,现在是跑bean后置处理器). cacheKey自然是mathCaculator. 然后返回一个包装类. 即进入到源码的第11行.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// 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;
}

​ 源码27

直接跳到源码27的第14行. 注释写的很明确——如果有能用于此bean的通知方法(即getAdvicesAndAdvisorsForBean方法,就不跟进去了,这里面涉及到使用@Pointcut表达式计算是否匹配,并且还对 增强器做了排序),就创建代理.

显然我们有四个(因为切面类LogAspects中有4个通知方法). 然后advisedBeans中加入了cacheKey=mathCaculator需要增强的信息, 并且来到了关键的第17行代码——这一行代码才是真正创建代理类的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}

ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);

if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}

return proxyFactory.getProxy(getProxyClassLoader());
}

​ 源码28

proxyFactory是创建代理的工厂,它里面保存了适用于bean的增强器, 主要看最后一行,继续跟

1
2
3
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
1
2
3
4
5
6
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}

可见,一个是JdkDynamicAopProxy一个是ObjenesisCglibAopProxy(即一个是jdk的动态代理,一个是cglib的动态代理)

具体是哪个,由Spring决定. 一般如果实现了接口,则使用前者,否则使用后者. 因为我们的DEMO【1】中没有实现接口,所以返回的是cglib增强的动态代理. 回到源码27, 第17行的proxy就是cglib增强的动态代理. 而且我们返回的也是这个动态代理. 所以最后注册到ioc中的就是代理对象. 即ioc容器中获取到的也是这种代理对象而不是对象本身.

注意,这里有必要讲一下最后返回的增强对象(即源码28下面的第一个源码的第二行)到底长什么样子(即最后的MathCaculator\$\$EnhancerBySpringCGLIB对象到底长什么样子)

​ 图1

可以看出,MathCaculator\$\$EnhancerBySpringCGLIB就是一堆的拦截器链. 这些拦截器链是在源码28下的第一个源码的第二行的getProxy时做的. 具体源码就不跟了 ,反正你要知道,放进ioc中的增强后的对象其实和原本的MathCalculator没一毛钱关系,它其实就是一堆的cglib拦截器链.

wait,wait,wait, 这里我们关心一下我们使用spring的时候一直谈论但是其实很多人并不清楚的两个问题

  1. ioc容器到底是什么?
  2. 注入bean(注意,注册和注入是不一样的,注册是注册bean的定义(添加到【3】中获取的beanDefinitionNames中去),而注入是将创建好的bean放进ioc容器中去)到底是啥?

从源码26的第11行创建增强bean返回之后,一路返回,返回到源码11的第21行. 然后源码11的第26行,就是将源码11的第21行得到的singletonObject加入到org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.singletonObjects中去.

这个singletonObjects属性(一个ConcurrentHashMap<String, Object>(256))就是我们天天谈论的ioc容器.

后面你会看到,我们取bean的时候也是从这个singletonObjects中取的.

所以我们继续关心下一个话题

从IOC容器中获取bean的流程

上一节我们已经知道了注入到ioc中的是代理对象. 现在考虑代理对象上调用目标方法.

不过,在此之前,我们先说清楚是怎么从ioc容器中取得bean的.

还是以demo【1】为例.

1
MathCaculator mathCaculator = applicationContext.getBean(MathCaculator.class);

这一行代码就是我们从ioc容器中获取MathCaculator类型的bean. 跟进源码会来到

org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(Class, Object…)(其实正因为如此,)

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
BeanFactory parent = getParentBeanFactory();
if (parent != null) {
return parent.getBean(requiredType, args);
}
throw new NoSuchBeanDefinitionException(requiredType);
}

​ 源码29

会在源码29的第5行返回. 跟进源码29的第三行.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@SuppressWarnings("unchecked")
private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
Assert.notNull(requiredType, "Required type must not be null");
String[] candidateNames = getBeanNamesForType(requiredType);

if (candidateNames.length > 1) {
List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
for (String beanName : candidateNames) {
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
autowireCandidates.add(beanName);
}
}
if (!autowireCandidates.isEmpty()) {
candidateNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
}
}

if (candidateNames.length == 1) {
String beanName = candidateNames[0];
return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
}
...

​ 源码30

源码30的第18行的candidateNames长度是1,就只有一个mathCaculator,所以跟进源码30第20行的getBean方法. 继续跟进doGetBean,来到了

org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String, Class, Object[], boolean)

1
2
3
4
5
6
7
8
9
10
11
12
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {

final String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
...

​ 源码31

这其实就是源码10上面打省略号的部分. 这里第10行获取sharedInstance不再为null了,所以不会走源码10. 跟进源码31的第10行. 我们来到了org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String, boolean)

1
2
3
4
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
...

​ 源码32

第二行就是从singletonObjects获取到非null的singletonObject(就是一个MathCaculator$$EnhancerBySpringCGLIB 对象). 所以直接返回,而不会走下面了.

于是返回源码29的第五行,最终App.main 中从容器中获取的就是一个MathCaculator\$\$EnhancerBySpringCGLIB对象. 所以讲清楚这个问题之后,我们来看看调用MathCaculator$$EnhancerBySpringCGLIB的div方法(即目标方法)的过程.

增强对象调用目标方法的流程

调用目标方法的时候debug进入到org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy)方法, 此方法从名称上也能看出来是拦截一下目标方法, 注意,之前我们说了MathCaculator\$\$EnhancerBySpringCGLIB对象其实就是一堆的cglib拦截器链,这里正好就是图1的第一个拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 获取拦截器链
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;

​ 源码33

源码33其实就是获取拦截器链,获取谁的拦截器链呢?

method=public int com.yfs.bean.MathCaculator.div(int,int)

targetClass=class com.yfs.bean.MathCaculator

target=com.yfs.bean.MathCaculator@338c99c8

advised就是一个ProxyFactory

即获取method(目标方法)的拦截器链.

从上面的官方注释也可以看出——如果没有拦截器链(拦截器链为空),则直接执行目标方法,否则把目标对象、目标方法、拦截器链等信息创建一个CglibMethodInvocation对象(简称mi),并且执行mi.proceed() 方法(因为CglibMethodInvocation中包含了拦截器链,所以其实proceed方法就是触发整个拦截器链).得到的结果retVal,再进一步对retVal进行处理(即processReturnType)

这是大体流程,而且我们能猜测到这个拦截器链非常重要——它应该包含了通知方法. 所以我们要考察一下拦截器链是怎么获取的. 跟进源码33的第二行源码

org.springframework.aop.framework.AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice(Method, Class<?>)

1
2
3
4
5
6
7
8
9
10
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}

​ 源码34

对于第一次进来,第四行一定是null,则跟进源码34的第五行,我们来到DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}

return interceptorList; // 就是要返回的拦截器链
}

​ 源码35

源码35中的config.getAdvisors()得到的就是4个通知方法. 遍历这些通知方法(InstantiationModelAwarePointcutAdvisor类型)封装成MethodInterceptor[](源码35的第11行——MethodInterceptor[] interceptors = registry.getInterceptors(advisor); 转换的过程就是判断是不是MethodInterceptor, 如果是,则直接加入,如果不是,找一堆的适配器([org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter, org.springframework.aop.framework.adapter.AfterReturningAdviceAdapter, org.springframework.aop.framework.adapter.ThrowsAdviceAdapter],也就是这三种通知需要转为MethodInterceptor)将其转换为MethodInterceptor后加进去), 最后加入到要返回的interceptorList中去.

所以,所谓的拦截器链其实就是通知方法被转换为MethodInterceptor接口组成的链表,然后都是MethodInterceptor在执行。下面我们看看拦截器链长什么样子

​ 图2

拦截器链如何执行

上一节我们最后得到的结论是将拦截器链封装进了一个mi(MethodInvocation,具体就是CglibMethodInvocation,你可以理解其为方法执行链上下文). 然后调用该mi的proceed方法. 这个proceed方法将触发拦截器链的调用.本节我们谈谈触发的流程以及包含的设计模式.

我们回到源码33的第16行. 即CglibMethodInvocation调用其proceed方法. 注意CglibMethodInvocation是ReflectiveMethodInvocation的子类,其实是调用ReflectiveMethodInvocation的proceed方法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint(); // 反射执行目标方法
}

Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);// 获取当前拦截器链中的拦截器
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
} // 上面的if不会走
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); // 责任链设计模式
}
}

​ 源码36

上述源码就是经典的责任链设计模式. 对应【4】进行查看. 唯一需要注意的是,这里是逆序调用拦截器链中的各个拦截器的. 因为源码36的第27行依次进入的源码是

ExposeInvocationInterceptor.invoke

1
2
3
4
5
6
7
8
9
10
11
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}

​ 源码37

AspectJAfterThrowingAdvice.invoke

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) { // 捕捉 源码39、40、41中的异常,如果没有异常,则不会执行throwing方法
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex; // 往上抛
}
}

​ 源码38

AfterReturningAdviceInterceptor.invoke

1
2
3
4
5
6
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed(); // 源码40、41遇到了异常的话,是不会执行returning的切面方法的
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}

​ 源码39

AspectJAfterAdvice.invoke

1
2
3
4
5
6
7
8
9
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}

​ 源码40

MethodBeforeAdviceInterceptor.java

1
2
3
4
5
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}

​ 源码41

注意源码41,即最后进入的拦截器,是先调用通知方法再proceed. 而回到源码36第4行的话,满足第四行条件,就执行源码36第5行了, 即反射调用目标方法. 然后逐层退出. 因此我们知道了整个拦截器栈(因为逆序,所以用栈其实更合适)的执行过程是

before–>目标方法–>after–>afterreturning(正常)/afterthrowing(异常)–>重新设置回原先的MethodInvocation

所以与拦截器chains这根链表中的顺序恰好相反. 所以叫拦截器栈更为合适,而不是叫拦截器链.

至此,我们就弄清楚了Spring AOP 的所有原理.

DEMO

【1】https://github.com/yfsyfs/backend/tree/master/spring-annotation-aop

【2】https://yfsyfs.github.io/2019/06/10/BeanPostProcessor-%E5%8E%9F%E7%90%86%E6%B5%85%E6%9E%90/

【3】https://yfsyfs.github.io/2019/06/13/Profile-%E5%8E%9F%E7%90%86/

【4】https://yfsyfs.github.io/2019/06/14/Spring-AOP-%E4%B8%AD%E7%9A%84%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F/