Spring——AOP原理及源码

原文链接:https://www.cnblogs.com/Unicron/p/12386776.html

从AOP实例的构建到重要组件分析、基本运行流程、关键方法调用、原理总结等几个方面一步步分解AOP源码

一、项目构建

读者可直接下载示例工程,或复制以下的代码到本地工程开启教程。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tlj</groupId>
    <artifactId>spring-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
    </dependencies>


</project>
package config;

import aop.LogAspects;
import aop.MathCalculator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@Configuration
public class ConfigOfAOP {

    @Bean
    public MathCalculator calculator(){
        return new MathCalculator();
    }

    @Bean
    public LogAspects logAspects(){
        return new LogAspects();
    }
}
package aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;

import java.util.Arrays;

/**
 * 切面类
 */
@Aspect
public class LogAspects {

    @Pointcut("execution(public int aop.MathCalculator.*(..))")
    public void poinCut(){}

    @Before("poinCut()")
    public void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        System.out.println(joinPoint.getSignature().getName()+" 运行。。。@Before "+ Arrays.asList(args));
    }

    @After("poinCut()")
    public void  logEnd(){
        System.out.println("除法结束..@After");
    }

    @AfterReturning(value = "poinCut()",returning = "result")//获取方法返回值
    public void logReturning(Object result){
        System.out.println("除法正常返回..@AfterReturning "+result);
    }

    @AfterThrowing(value = "poinCut()",throwing = "e")
    public void logException(Exception e){
        System.out.println("除法异常..@AfterThrowing "+e);
    }
}
package aop;

public class MathCalculator {

    public int div(int i,int j){
        System.out.println("MathCalculator");
        return i/j;
    }
}

项目目录结构如下:

img

到这里,我们的项目就构建完了。

二、日志切面方法测试

打开测试类,运行测试方法

img


最终效果

总共打印了四行,第二行是业务方法的调用,其他都是调用日志切面类中的方法打印的。

这就是AOP的使用效果,除了用在日志,还有其他很多用法,这里就不赘述了。

三、关键组件探究

为什么AOP能在业务方法调用的前后和发生异常时调用切面方法呢,首先我们需要了解它引入了什么组件。

为了让AOP起作用,我们需要在配置类上添加@EnableAspectJAutoProxy注解,从字面上看,翻译为启动切面自动代理,那它是怎么启动的呢

ctrl+鼠标左键进入这个注解,我们可以看到EnableAspectJAutoProxy接口使用@Import注解导入了AspectJAutoProxyRegistrar这个类

img


再次ctrl+鼠标左键进入AspectJAutoProxyRegistrar,可以看到,它实现了ImportBeanDefinitionRegistrar接口。

此接口中的registerBeanDefinitions方法,正是用来向容器中注册组件的。

接下来来看@EnableAspectJAutoProxy注解到底给容器中注册了什么组件。这是AOP实现的关键。

img

四、调试寻找组件

如下图,我们在ImportBeanDefinitionRegistrar接口的注册方法中打上断点。

img点击debug开始调试,程序来到了AspectJAutoProxyRegistrar的registerBeanDefinitions方法

正在执行的是AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)

(字面意思为:注册切面自动代理创造组件如果需要的话)

img


接着进入这个方法直到以下这个方法,可以看到返回的是BeanDefinition类型,而BeanDefinition是用来保存bean定义信息的

img

上图所示,一进来先进行判断,如果容器中存在AUTO_PROXY_CREATOR_BEAN_NAME定义信息,进行一些操作,最后return null。

如果不存在,可以看到在125行已经有注册名为AUTO_PROXY_CREATOR_BEAN_NAME的组件的动作,要将定义信息注册到容器中。

把鼠标放在AUTO_PROXY_CREATOR_BEAN_NAME上,可以看到它名为internalAutoProxyCreator

img

接着我们进行下一步,到110行时,显然第一次容器中不存在这个类,所以跳过if{}中的内容

到121行时,通过bean的各种定义信息,new一个定义bean,用来保存这个bean的各种定义信息

通过cls的信息,发现注册的internalAutoProxyCreator实际为AnnotationAwareAspectJAutoProxyCreator

img

到125行时,已经设置好AnnotationAwareAspectJAutoProxyCreator的各种属性

并将其命名为internalAutoProxyCreator注册进容器,在126行进行返回。

注意:这里注册的是BeanDefinition,也就是bean的定义信息,并没有创建bean实例

总结

到此为止@EnableAspectJAutoProxy给容器中添加了internalAutoProxyCreator的BeanDefinition组件

internalAutoProxyCreator中实际又是AnnotationAwareAspectJAutoProxyCreator这个类

所以我们可以得出AnnotationAwareAspectJAutoProxyCreator就是实现AOP的核心组件

接下来我们来看AnnotationAwareAspectJAutoProxyCreator的继承关系,看它到底是什么

五、AnnotationAwareAspectJAutoProxyCreator

进入这个类,发现它继承了AspectJAwareAdvisorAutoProxyCreator

img

那么AspectJAwareAdvisorAutoProxyCreator又是什么呢,接着进入AspectJAwareAdvisorAutoProxyCreator

发现AspectJAwareAdvisorAutoProxyCreator又继承了AbstractAdvisorAutoProxyCreator

img

我们接着进入AbstractAdvisorAutoProxyCreator中查看

可以看到AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator

img

再进入AbstractAutoProxyCreator

可以看到AbstractAutoProxyCreator继承了ProxyProcessorSupport

并实现了SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware两个接口

img

由于接下来继承的ProxyProcessorSupport是一个基础工具类,就不往下分析了


接下来我们主要看这两个接口

SmartInstantiationAwareBeanPostProcessor:从名字中带有PostProcessor看出是一个后置处理器接口

BeanFactoryAware:底层组件接口,和其他XXXAware一样,实现XXXAware接口就可以调用XXX组件

经过层层的进入,可以得到如下的关系:

img

img

从图得出结论——AnnotationAwareAspectJAutoProxyCreator是一个后置处理器后置处理器原理

总结

  经过以上五个步骤,我们了解了AOP的使用效果

  找到了AOP的核心组件AnnotationAwareAspectJAutoProxyCreator

  理清了AnnotationAwareAspectJAutoProxyCreator的继承实现关系

  发现了AOP的核心组件本质上是一个后置处理器

接下来我们就从后置处理器和BeanFactoryAware的角度来看看AnnotationAwareAspectJAutoProxyCreator的BeanDefinition创建完成后都做了什么。

一、设置调试断点

我们分别进入四个有关类,在类中与后置处理器和BeanFactoryAware有关的方法上打上断点。最终效果如下:

AbstractAutoProxyCreator.setBeanFactory
AbstractAutoProxyCreator有后置处理器逻辑
{
  postProcessBeforeInstantiation()
  postProcessAfterInitialization()
}
AbstractAdvisorAutoProxyCreator.initBeanFactory
AbstractAdvisorAutoProxyCreator.setBeanFactory
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory

最后,在配置类中给两个bean方法打上断点。

二、调试过程

开始调试,我们会发现还是先来到上一篇的AnnotationAwareAspectJAutoProxyCreator的BeanDenation创建过程。

img

左下角frames框中选到refresh方法可以看到,AnnotationAwareAspectJAutoProxyCreator的BeanDenation的创建是invokeBeanFactoryPostProcessors()方法调用来的。

调用这个方法在上下文中生成后置处理器的BeanDefinition加入容器中。

下一步的registerBeanPostProcessors才是注册后置处理器(利用BeanDefinition的信息注册对应Bean),也是本篇的重点。

img

为了让它快速创建完BeanDefinition,这里我们直接快进到下一个断点。

img

程序先来到了AbstractAdvisorAutoProxyCreator的setBeanFactory方法

img

为了从头看起,还是先在frames框中选到refresh方法,可以看到来到了refresh的下一方法,将要开始注册后置处理器。

img


二点一、registerBeanPostProcessors()

我们继续在frames中往上点,直到来到PostProcessorRegistrationDelegate.registerBeanPostProcessors()

img

方法有点长,但关键只在其中几个地方,我们将在下面进行针对分析

 1 public static void registerBeanPostProcessors(
 2             ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
 3 
 4         String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
 5 
 6         // Register BeanPostProcessorChecker that logs an info message when
 7         // a bean is created during BeanPostProcessor instantiation, i.e. when
 8         // a bean is not eligible for getting processed by all BeanPostProcessors.
 9         int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
10         beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
11 
12         // Separate between BeanPostProcessors that implement PriorityOrdered,
13         // Ordered, and the rest.
14         List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
15         List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
16         List<String> orderedPostProcessorNames = new ArrayList<String>();
17         List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
18         for (String ppName : postProcessorNames) {
19             if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
20                 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
21                 priorityOrderedPostProcessors.add(pp);
22                 if (pp instanceof MergedBeanDefinitionPostProcessor) {
23                     internalPostProcessors.add(pp);
24                 }
25             }
26             else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
27                 orderedPostProcessorNames.add(ppName);
28             }
29             else {
30                 nonOrderedPostProcessorNames.add(ppName);
31             }
32         }
33 
34         // First, register the BeanPostProcessors that implement PriorityOrdered.
35         sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
36         registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
37 
38         // Next, register the BeanPostProcessors that implement Ordered.
39         List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
40         for (String ppName : orderedPostProcessorNames) {
41             BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
42             orderedPostProcessors.add(pp);
43             if (pp instanceof MergedBeanDefinitionPostProcessor) {
44                 internalPostProcessors.add(pp);
45             }
46         }
47         sortPostProcessors(orderedPostProcessors, beanFactory);
48         registerBeanPostProcessors(beanFactory, orderedPostProcessors);
49 
50         // Now, register all regular BeanPostProcessors.
51         List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
52         for (String ppName : nonOrderedPostProcessorNames) {
53             BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
54             nonOrderedPostProcessors.add(pp);
55             if (pp instanceof MergedBeanDefinitionPostProcessor) {
56                 internalPostProcessors.add(pp);
57             }
58         }
59         registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
60 
61         // Finally, re-register all internal BeanPostProcessors.
62         sortPostProcessors(internalPostProcessors, beanFactory);
63         registerBeanPostProcessors(beanFactory, internalPostProcessors);
64 
65         // Re-register post-processor for detecting inner beans as ApplicationListeners,
66         // moving it to the end of the processor chain (for picking up proxies etc).
67         beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
68     }

4:获取所有后置处理器的名字

14~32:对实现不同接口的后置处理器进行分类

35~48:对上面的分类分别进行处理,因为实现的是Ordered接口,我们只关注39~48行

img

40~46:遍历分好的实现了Ordered接口的后置处理器名,利用beanFactory.getBean(ppName, BeanPostProcessor.class)来获取


二点二、doGetBean()

有了以上的步骤,我们主要来看beanFactory是怎么获取的

img

可以看到,先来到了getBean方法,然后又进入了doGetBean方法。下面我们来看doGetBean做了什么。

  1 /**
  2      * Return an instance, which may be shared or independent, of the specified bean.
  3      * @param name the name of the bean to retrieve
  4      * @param requiredType the required type of the bean to retrieve
  5      * @param args arguments to use when creating a bean instance using explicit arguments
  6      * (only applied when creating a new instance as opposed to retrieving an existing one)
  7      * @param typeCheckOnly whether the instance is obtained for a type check,
  8      * not for actual use
  9      * @return an instance of the bean
 10      * @throws BeansException if the bean could not be created
 11      */
 12     @SuppressWarnings("unchecked")
 13     protected <T> T doGetBean(
 14             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
 15             throws BeansException {
 16 
 17         final String beanName = transformedBeanName(name);
 18         Object bean;
 19 
 20         // Eagerly check singleton cache for manually registered singletons.
 21         Object sharedInstance = getSingleton(beanName);
 22         if (sharedInstance != null && args == null) {
 23             if (logger.isDebugEnabled()) {
 24                 if (isSingletonCurrentlyInCreation(beanName)) {
 25                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
 26                             "' that is not fully initialized yet - a consequence of a circular reference");
 27                 }
 28                 else {
 29                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
 30                 }
 31             }
 32             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 33         }
 34 
 35         else {
 36             // Fail if we're already creating this bean instance:
 37             // We're assumably within a circular reference.
 38             if (isPrototypeCurrentlyInCreation(beanName)) {
 39                 throw new BeanCurrentlyInCreationException(beanName);
 40             }
 41 
 42             // Check if bean definition exists in this factory.
 43             BeanFactory parentBeanFactory = getParentBeanFactory();
 44             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 45                 // Not found -> check parent.
 46                 String nameToLookup = originalBeanName(name);
 47                 if (args != null) {
 48                     // Delegation to parent with explicit args.
 49                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 50                 }
 51                 else {
 52                     // No args -> delegate to standard getBean method.
 53                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 54                 }
 55             }
 56 
 57             if (!typeCheckOnly) {
 58                 markBeanAsCreated(beanName);
 59             }
 60 
 61             try {
 62                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 63                 checkMergedBeanDefinition(mbd, beanName, args);
 64 
 65                 // Guarantee initialization of beans that the current bean depends on.
 66                 String[] dependsOn = mbd.getDependsOn();
 67                 if (dependsOn != null) {
 68                     for (String dep : dependsOn) {
 69                         if (isDependent(beanName, dep)) {
 70                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 71                                     "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 72                         }
 73                         registerDependentBean(dep, beanName);
 74                         getBean(dep);
 75                     }
 76                 }
 77 
 78                 // Create bean instance.
 79                 if (mbd.isSingleton()) {
 80                     sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
 81                         @Override
 82                         public Object getObject() throws BeansException {
 83                             try {
 84                                 return createBean(beanName, mbd, args);
 85                             }
 86                             catch (BeansException ex) {
 87                                 // Explicitly remove instance from singleton cache: It might have been put there
 88                                 // eagerly by the creation process, to allow for circular reference resolution.
 89                                 // Also remove any beans that received a temporary reference to the bean.
 90                                 destroySingleton(beanName);
 91                                 throw ex;
 92                             }
 93                         }
 94                     });
 95                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 96                 }
 97 
 98                 else if (mbd.isPrototype()) {
 99                     // It's a prototype -> create a new instance.
100                     Object prototypeInstance = null;
101                     try {
102                         beforePrototypeCreation(beanName);
103                         prototypeInstance = createBean(beanName, mbd, args);
104                     }
105                     finally {
106                         afterPrototypeCreation(beanName);
107                     }
108                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
109                 }
110 
111                 else {
112                     String scopeName = mbd.getScope();
113                     final Scope scope = this.scopes.get(scopeName);
114                     if (scope == null) {
115                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
116                     }
117                     try {
118                         Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
119                             @Override
120                             public Object getObject() throws BeansException {
121                                 beforePrototypeCreation(beanName);
122                                 try {
123                                     return createBean(beanName, mbd, args);
124                                 }
125                                 finally {
126                                     afterPrototypeCreation(beanName);
127                                 }
128                             }
129                         });
130                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
131                     }
132                     catch (IllegalStateException ex) {
133                         throw new BeanCreationException(beanName,
134                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
135                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
136                                 ex);
137                     }
138                 }
139             }
140             catch (BeansException ex) {
141                 cleanupAfterBeanCreationFailure(beanName);
142                 throw ex;
143             }
144         }
145 
146         // Check if required type matches the type of the actual bean instance.
147         if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
148             try {
149                 return getTypeConverter().convertIfNecessary(bean, requiredType);
150             }
151             catch (TypeMismatchException ex) {
152                 if (logger.isDebugEnabled()) {
153                     logger.debug("Failed to convert bean '" + name + "' to required type '" +
154                             ClassUtils.getQualifiedName(requiredType) + "'", ex);
155                 }
156                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
157             }
158         }
159         return (T) bean;
160     }

17:获取后置处理器的名称(这里也就是internalAutoProxyCreator)

21:根据bean名字获取对应单例

22~33:如果获取到的bean不为空,进行一系列操作(这里的internalAutoProxyCreator是第一次获取,bean应该是空,所以我们跳过22~33)

61:getMergedLocalBeanDefinition() 根据传入的后置处理器名称,获取其所有信息,在这里也就是从internalAutoProxyCreator的BeanDefinition中获取必要信息,这是为创建bean做准备。

79:判断如果是单例,调用getSingleton()来获取

这里我们先不急着进入getSingleton()方法,接着往下看先。

130:bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd) 将79行获取的scopedInstance包装为bean

159:返回bean

ok,getSingleton()的获取是要返回的,所以这步是关键,接下来我们来看看getSingleton()。

img

一直往上走,最终我们来到doCreateBean(),说明获取不到,接下来需要创建bean了


二点三、doCreateBean()

  1 /**
  2      * Actually create the specified bean. Pre-creation processing has already happened
  3      * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
  4      * <p>Differentiates between default bean instantiation, use of a
  5      * factory method, and autowiring a constructor.
  6      * @param beanName the name of the bean
  7      * @param mbd the merged bean definition for the bean
  8      * @param args explicit arguments to use for constructor or factory method invocation
  9      * @return a new instance of the bean
 10      * @throws BeanCreationException if the bean could not be created
 11      * @see #instantiateBean
 12      * @see #instantiateUsingFactoryMethod
 13      * @see #autowireConstructor
 14      */
 15     protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
 16             throws BeanCreationException {
 17 
 18         // Instantiate the bean.
 19         BeanWrapper instanceWrapper = null;
 20         if (mbd.isSingleton()) {
 21             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 22         }
 23         if (instanceWrapper == null) {
 24             instanceWrapper = createBeanInstance(beanName, mbd, args);
 25         }
 26         final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
 27         Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
 28         mbd.resolvedTargetType = beanType;
 29 
 30         // Allow post-processors to modify the merged bean definition.
 31         synchronized (mbd.postProcessingLock) {
 32             if (!mbd.postProcessed) {
 33                 try {
 34                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 35                 }
 36                 catch (Throwable ex) {
 37                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 38                             "Post-processing of merged bean definition failed", ex);
 39                 }
 40                 mbd.postProcessed = true;
 41             }
 42         }
 43 
 44         // Eagerly cache singletons to be able to resolve circular references
 45         // even when triggered by lifecycle interfaces like BeanFactoryAware.
 46         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 47                 isSingletonCurrentlyInCreation(beanName));
 48         if (earlySingletonExposure) {
 49             if (logger.isDebugEnabled()) {
 50                 logger.debug("Eagerly caching bean '" + beanName +
 51                         "' to allow for resolving potential circular references");
 52             }
 53             addSingletonFactory(beanName, new ObjectFactory<Object>() {
 54                 @Override
 55                 public Object getObject() throws BeansException {
 56                     return getEarlyBeanReference(beanName, mbd, bean);
 57                 }
 58             });
 59         }
 60 
 61         // Initialize the bean instance.
 62         Object exposedObject = bean;
 63         try {
 64             populateBean(beanName, mbd, instanceWrapper);
 65             if (exposedObject != null) {
 66                 exposedObject = initializeBean(beanName, exposedObject, mbd);
 67             }
 68         }
 69         catch (Throwable ex) {
 70             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 71                 throw (BeanCreationException) ex;
 72             }
 73             else {
 74                 throw new BeanCreationException(
 75                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
 76             }
 77         }
 78 
 79         if (earlySingletonExposure) {
 80             Object earlySingletonReference = getSingleton(beanName, false);
 81             if (earlySingletonReference != null) {
 82                 if (exposedObject == bean) {
 83                     exposedObject = earlySingletonReference;
 84                 }
 85                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
 86                     String[] dependentBeans = getDependentBeans(beanName);
 87                     Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
 88                     for (String dependentBean : dependentBeans) {
 89                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
 90                             actualDependentBeans.add(dependentBean);
 91                         }
 92                     }
 93                     if (!actualDependentBeans.isEmpty()) {
 94                         throw new BeanCurrentlyInCreationException(beanName,
 95                                 "Bean with name '" + beanName + "' has been injected into other beans [" +
 96                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
 97                                 "] in its raw version as part of a circular reference, but has eventually been " +
 98                                 "wrapped. This means that said other beans do not use the final version of the " +
 99                                 "bean. This is often the result of over-eager type matching - consider using " +
100                                 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
101                     }
102                 }
103             }
104         }
105 
106         // Register bean as disposable.
107         try {
108             registerDisposableBeanIfNecessary(beanName, bean, mbd);
109         }
110         catch (BeanDefinitionValidationException ex) {
111             throw new BeanCreationException(
112                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
113         }
114 
115         return exposedObject;
116     }

26:创建bean

64:populateBean(beanName, mbd, instanceWrapper) 给bean的属性赋值

66:initializeBean(beanName, exposedObject, mbd)初始化bean

下面我们来看这个初始化bean都做了什么


二点四、initializeBean()

 1 /**
 2      * Initialize the given bean instance, applying factory callbacks
 3      * as well as init methods and bean post processors.
 4      * <p>Called from {@link #createBean} for traditionally defined beans,
 5      * and from {@link #initializeBean} for existing bean instances.
 6      * @param beanName the bean name in the factory (for debugging purposes)
 7      * @param bean the new bean instance we may need to initialize
 8      * @param mbd the bean definition that the bean was created with
 9      * (can also be {@code null}, if given an existing bean instance)
10      * @return the initialized bean instance (potentially wrapped)
11      * @see BeanNameAware
12      * @see BeanClassLoaderAware
13      * @see BeanFactoryAware
14      * @see #applyBeanPostProcessorsBeforeInitialization
15      * @see #invokeInitMethods
16      * @see #applyBeanPostProcessorsAfterInitialization
17      */
18     protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
19         if (System.getSecurityManager() != null) {
20             AccessController.doPrivileged(new PrivilegedAction<Object>() {
21                 @Override
22                 public Object run() {
23                     invokeAwareMethods(beanName, bean);
24                     return null;
25                 }
26             }, getAccessControlContext());
27         }
28         else {
29             invokeAwareMethods(beanName, bean);
30         }
31 
32         Object wrappedBean = bean;
33         if (mbd == null || !mbd.isSynthetic()) {
34             wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
35         }
36 
37         try {
38             invokeInitMethods(beanName, wrappedBean, mbd);
39         }
40         catch (Throwable ex) {
41             throw new BeanCreationException(
42                     (mbd != null ? mbd.getResourceDescription() : null),
43                     beanName, "Invocation of init method failed", ex);
44         }
45 
46         if (mbd == null || !mbd.isSynthetic()) {
47             wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
48         }
49         return wrappedBean;
50     }

一进来我们是停在29行的invokeAwareMethods(beanName, bean),这里先不看它

我们来关注一下initializeBean的几个重要流程

1、invokeAwareMethods

2、34行applyBeanPostProcessorsBeforeInitialization

3、38行invokeInitMethods

4、47行applyBeanPostProcessorsAfterInitialization

先执行invokeAwareMethods,调用那些XXXAware方法,然后执行后置处理器的applyBeanPostProcessorsBeforeInitialization方法,接着执行初始化方法,最后执行后置处理器的applyBeanPostProcessorsAfterInitialization方法,这也是我们的后置处理器为什么能在bean初始化前后调用方法的原因了。

现在我们往下进入invokeAwareMethods

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

invokeAwareMethods方法先判断是哪个类型的Aware接口,然后调用对应的set方法,所以它最终来到了我们的断点,setBeanFactory()方法

img

接下来我们一路点击下一步,直到下图,这个BeanPostProcessor就创建完了,并通过orderedPostProcessors.add(pp)先添加到orderedPostProcessors中

再通过registerBeanPostProcessors(beanFactory, orderedPostProcessors)添加到beanFactory中

img

总结

  以上整个过程,是创建完AnnotationAwareAspectJAutoProxyCreator后置处理器bean并存入beanFactory的过程。

  

  下一篇将来探寻AnnotationAwareAspectJAutoProxyCreator在作为后置处理器存入bean工程之后的事。

 在上一篇中,我们创建并在BeanFactory中注册了AnnotationAwareAspectJAutoProxyCreator组件。本篇我们将要探究,这个组件是在哪里以及何时发挥作用的。

调试的起点

  我们直接开始调试,之前看过的断点就直接跳过了,一直跳到下一个断点直到来到 AbstractAutoProxyCreator.postProcessBeforeInstantiation()

img

不同后置处理器的差异

  这个方法名叫postProcessBeforeInstantiation,仔细看会发现和后置处理器BeanPostProcessor是不一样的,我们拉到上面能看到AbstractAutoProxyCreator实现的是

SmartInstantiationAwareBeanPostProcessor这个接口

img

进入SmartInstantiationAwareBeanPostProcessor这个接口会看到它又继承了InstantiationAwareBeanPostProcessor

img

再进入InstantiationAwareBeanPostProcessor可以看到它继承的也是BeanPostProcessor

img

但InstantiationAwareBeanPostProcessor实现的两个方法名字如下:

img

不同于BeanPostProcessor中的postProcessBeforeInitialization和postProcessAfterInitialization

可见后置处理器也是存在差异的。

*结论:AnnotationAwareAspectJAutoProxyCreator是InstantiationAwareBeanPostProcessor类型的后置处理器*


从头看起

我们还是从头看起,看程序是怎么走到这一步的。

img

在Frames框中从测试方法开始,往上查看:

1、refresh刷新创建容器实例化剩下的所有单实例bean

2、finishBeanFactoryInitialization(beanFactory) 实例化剩下的所有单实例bean

img

3、再往上走,*beanFactory调用了*preInstantiateSingletons()

img

4、一直往上走直到*AbstractAutowireCapableBeanFactory.*createBean(),如下图

img

 第四步经历了:

  1. 1.   getBean
    1.   doGetBean
    2.   getSingleton
    3.   getObject
    4.   createBean

 这一系列过程和上篇中创建AnnotationAwareAspectJAutoProxyCreator的过程是一模一样的,

  不过上篇创建AnnotationAwareAspectJAutoProxyCreator时,我们经历上述过程后进入的是doCreateBean方法,最终创建出了bean

而在这里,我们执行的是在doCreateBean上面的resolveBeforeInstantiation方法


(这时AnnotationAwareAspectJAutoProxyCreator早已经创建好放入容器,我们现在做的是完成其他所有bean的实例化)

如下图,我们可以发现,当前的resolveBeforeInstantiation正是在doCreateBean方法的上面

说明当时也调用了resolveBeforeInstantiation方法,只不过返回的bean为null,所以才有了调用doCreateBean来创建bean

img


现在我们可以知道,在所有bean创建之前,都会先调用resolveBeforeInstantiation方法

  方法上的注释表明,方法会给后置处理器一个机会来返回目标bean实例的代理对象。也就是返回一个代理对象来代替我们将要创建的的目标bean

  现在我们把注意力放在resolveBeforeInstantiation这个方法上

  在方法栈中继续往上查看,我们来到了resolveBeforeInstantiation方法的1011行

  从1011到1013行,调用applyBeanPostProcessorsBeforeInstantiation返回bean,接着进行判断,如果返回的bean不为null

  接着执行applyBeanPostProcessorsAfterInitialization方法

img

  接下来我们先进入applyBeanPostProcessorsBeforeInstantiation方法,将会循环遍历所有的后置处理器

判断如果是InstantiationAwareBeanPostProcessor类型,就执行它的postProcessBeforeInstantiation方法

img

上面我们提到过后置处理器存在差异,我们的AnnotationAwareAspectJAutoProxyCreator刚好就是属于InstantiationAwareBeanPostProcessor这个类型

所以接下来我们来到当初设置的的后置处理器断点,并执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法

img

总结

   由以上整个过程,我们可以得出:在所有bean实例化的时候,都会调用AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法。方法尝试返回一个代理对象,用来代替我们的目标实例。

下一篇中,我们将探究后置处理器的方法,探究究竟是如何给实例创建代理对象。

前情回顾:

  上文我们一路分析了从容器创建开始直到我们的AOP注解导入的核心组件AnnotationAwareAspectJAutoProxyCreator执行postProcessBeforeInstantiation()方法的整个过程

  分析得到:在所有bean创建之前,都会调用resolveBeforeInstantiation方法来试图返回一个代理对象

img


本篇预告

下图可以看到resolveBeforeInstantiation方法包含了

applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);

applyBeanPostProcessorsAfterInitialization(bean, beanName);

两个方法

img

在本篇我们将完整走完 resolveBeforeInstantiation 全过程,并一直到返回代理对象为止


调试的起点

  开始调试,还是一路跳到下一断点,直到AbstractAutoProxyCreator.postProcessBeforeInstantiation()(从resolveBeforeInstantiation方法进入到这里的过程上一篇已经分析了)

img

img

可以看到当前的bean为org.springframework.context.event.internalEventListenerProcessor,和我们要测试的AOP无关。

因为当前方法打上了断点,所以我们调到下一个断点直到来到class aop.MathCalculator

img

 1 @Override
 2     public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
 3         Object cacheKey = getCacheKey(beanClass, beanName);
 4 
 5         if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
 6             if (this.advisedBeans.containsKey(cacheKey)) {
 7                 return null;
 8             }
 9             if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
10                 this.advisedBeans.put(cacheKey, Boolean.FALSE);
11                 return null;
12             }
13         }
14 
15         // Create proxy here if we have a custom TargetSource.
16         // Suppresses unnecessary default instantiation of the target bean:
17         // The TargetSource will handle target instances in a custom fashion.
18         if (beanName != null) {
19             TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
20             if (targetSource != null) {
21                 this.targetSourcedBeans.add(beanName);
22                 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
23                 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
24                 this.proxyTypes.put(cacheKey, proxy.getClass());
25                 return proxy;
26             }
27         }
28 
29         return null;
30     }

从上往下一步步step voer,下面是对应行的讲解

3、获取bean在容器中的缓存

5、判断目标源Bean中是否存在有当前bean的缓存信息。

(可以在21行看到添加目标源bean的操作,在23行就创建了代理对象。所以这步也是相当于判断当前bean是否已经创建过代理对象。)

  因为是第一次执行MathCalculator这个bean,这里我们是进入判断的

  接下来 this.advisedBeans.containsKey(cacheKey) 判断advisedBeans中是否有缓存(这里我们将advisedBeans称为增强器)

  我们这里判断是不满足的,接着往下走。

9、进行 isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName) 判断

  下面分别进入第九行的两个方法进行查看。

  一、isInfrastructureClass(beanClass) 是否是基础类型

    进入后我们会发现有如下两个方法

    super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass)

  img

  先进入父类的 isInfrastructureClass 方法,经过一系列判断,最后返回false,表明当前bean不是基础类型。

 img

 

  接着来到 isAspect(beanClass) ,通过类上是否有@Aspect注解来判断这个类是否是切面(这里 MathCalculator显然不是一个切面

  img

 返回出来可以看到 isInfrastructureClass(beanClass) 的判断为false

  img

  

  二、shouldSkip 判断是否要跳过

  img

  在方法中遍历所有的增强器,红框中表面获取的增强器便是日志方法。  

  并判断增强器是否是AspectJPointcutAdvisor类型,我们这里判断不满足

  末尾来到父类的 shouldSkip 方法,进入可以看到直接返回了 false

  img

 img

最终我们来到外层的判断,可以看到返回了false

img


退出 applyBeanPostProcessorsBeforeInstantiation 方法

接着来到下面这块代码,看注释表明如果存在自定义目标Source,我们将在此创建代理对象

img

step voer,在259行判断targetSource为null,所以这里是没有自定义目标Source的

我们一直往下走,走完 applyBeanPostProcessorsBeforeInstantiation 方法,直到回到 resolveBeforeInstantiation 方法,返回的bean为null

所以接下来也不会进入 applyBeanPostProcessorsAfterInitialization 方法

img

到此为止,我们的 resolveBeforeInstantiation 方法执行完了,从以上可以得知,方法没有给我们返回代理对象

如下图所示,我们将接着执行 createBean 流程,接下来将调用 doCreateBean

img


postProcessAfterInitialization方法探究

我们执行 doCreateBean 方法,来到了配置类的bean方法

img

接着跳到下一个断点直到 postProcessAfterInitialization 方法,下面的方法栈我们是熟悉的

从finishBeanFactoryInitialization一路到initializeBean

img

不过我们现在进入的是postProcessAfterInitialization

从下图的 initializeBean 方法的流程也可以看明白

前面执行完了 applyBeanPostProcessorsBeforeInitialization 和 invokeInitMethods 两个方法

img

下面进入 postProcessAfterInitialization 方法:

  如果先前的代理参考中不存在当前bean对象,就调用 wrapIfNecessary(bean, beanName, cacheKey) 并返回其结果

  img

 进入wrapIfNecessary(进行包装如果需要的话):

/**
     * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
     * @param bean the raw bean instance
     * @param beanName the name of the bean
     * @param cacheKey the cache key for metadata access
     * @return a proxy wrapping the bean, or the raw bean instance as-is
     */
    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;
    }

9~18行:还是先进行判断,是否是基础类型等,在这里我们判断都不是

21:拿到增强器放入 Object[] specificInterceptors 中

24~25:传入拿到的增强器等信息,创建代理对象

下面我们着重来看 getAdvicesAndAdvisorsForBean 拿增强器的过程:

  一进来先调用findEligibleAdvisors,找到合格的增强器(日志方法)

  img

 进入findEligibleAdvisors,方法先调用findCandidateAdvisors,获取所有候选增强器

  然后又调用findAdvisoersThatCanApply从候选增强器中选出可以用于当前bean的

  接着判断选出的增强器队列不为空,就给其排序,最后返回选出的增强器队列

   img

 

 findCandidateAdvisors 我们就不说了

  重点看看 findAdvisoersThatCanApply

  如下图,可以发现它是利用AopUtils,也就是AOP工具类进行筛选

   img

 进入工具类方法,看到方法又进行了一层判断,将最终符合条件的增强器(日志方法)放入选择队列中

   img

 获取完后我们一路返回,又回到了 findEligibleAdvisors

  如下图可以看到,最终排序完后将返回有五个增强器的增强器队列

img


创建代理对象

最终我们获取到了需要的增强器(日志方法)放入一个叫特殊拦截器的数组(这里暂且称为拦截器数组)

判断不为空后,将当前bean的缓存放入adviseBeans 中

接着调用createProxy来创建代理对象

img

 1 /**
 2      * Create an AOP proxy for the given bean.
 3      * @param beanClass the class of the bean
 4      * @param beanName the name of the bean
 5      * @param specificInterceptors the set of interceptors that is
 6      * specific to this bean (may be empty, but not null)
 7      * @param targetSource the TargetSource for the proxy,
 8      * already pre-configured to access the bean
 9      * @return the AOP proxy for the bean
10      * @see #buildAdvisors
11      */
12     protected Object createProxy(
13             Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
14 
15         if (this.beanFactory instanceo