美文网首页
AOP源码分析之AnnotationAwareAspectJAu

AOP源码分析之AnnotationAwareAspectJAu

作者: 会上树的程序猿 | 来源:发表于2020-05-27 21:20 被阅读0次

    上节我们通过注解@EnableAspectJAutoProxy作为Aop源码分析的入口,最后发现做了那么多工作仅仅是把AnnotationAwareAspectJAutoProxyCreator这个后置处理器注册和创建并进行添加操作,为啥说AnnotationAwareAspectJAutoProxyCreator是一个后置处理器,可以通过它的继承实现关系来发现如下图所示:

    AnnotationAwareAspectJAutoProxyCreator.png

    从它的家族类图不难发现AnnotationAwareAspectJAutoProxyCreator 是一个InstantiationAwareBeanPostProcessor类型的后置处理器,既然前面我们分析它的创建和注册过程,本节来看看在Aop中是如何用到它的,同样我们还是 以我们的测试类作为入口进行分析,测试代码如下:

     //Aop测试
    @Test
    public void testAop(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAop.class);
        MathCalculator calculator = applicationContext.getBean(MathCalculator.class);
        calculator.div(10,5);
    
        applicationContext.close();
    }
    

    分析的入口还是以我们AnnotationConfigApplicationContext容器的创建作为分析入口,跟踪代码来到:

     public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        this();
        this.register(componentClasses);
        this.refresh();
    }
    

    首先Dbug来到了AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(...)构造方法,其中核心的是 this.refresh()方法,此方法的作用之前也已经提到过了,继续跟踪代码来到此方法,其中如下的代码片段值得我们注意:

    this.finishBeanFactoryInitialization(beanFactory);
    

    这段代码主要的目的是完成我们beanFactory的初始化工作和创建剩下未创建的单实例bean(这里也就是我们自己的bean),继续跟踪代码来到:

    首先一进方法对我们的beanFactory进行判断,具体如下:

     if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }
    
    • 上述是判断容器中是否id为conversionService 的bean ,其他的都是类似的操作这里不在一一仔细看了,继续跟踪代码来到如下的代码片段:
    beanFactory.freezeConfiguration();
    

    这段代码的意思是,将我们的 bean的定义的元信息进行缓存,不在做进一步的变化,跟踪代码来到DefaultListableBeanFactory类中:

    private volatile String[] frozenBeanDefinitionNames;
    
      public void freezeConfiguration() {
        this.configurationFrozen = true;
        this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
    }
    
    Aop源码分析1.png

    接着我们来到如下的代码片段:

    beanFactory.preInstantiateSingletons();
    

    上述这段代码主要的目的是初始化剩下的单实例bean,跟踪代码来到:

     List<String> beanNames = new ArrayList(this.beanDefinitionNames);
    

    首先从beanDefinitionNames中获取所有的bean的definition信息,接着是循环创建每一个bean

    image.png

    获取到bean的definition 信息之后进行while循环处理,跟踪代码会发现其实质做了如下的判断处理:

    • bean的定义是否抽象,是否不是单例的,是否是懒加载的。

    • 通过如下代码来判断bean是否是一个BeanFactory类型的bean

      if (this.isFactoryBean(beanName)) {
                        bean = this.getBean("&" + beanName);
                        break;
                    }
    

    如果不是工厂Bean的话,通过this.getBean(beanName)来创建bean,继续跟踪代码来到类AbstractFactory类中:

    public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }
    

    继续跟踪代码来到#doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)方法:

    • 首先通过如下代码来获取当前要创建bean的name值
    String beanName = this.transformedBeanName(name);
    
    • 接着是通过如下代码从缓存中通过beanName去获取单实例bean,如果能获取到则说明该beanBean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
      Object sharedInstance = this.getSingleton(beanName);
    

    这里分为两种情况,如果从缓存拿到了当前要创建的bean,直接返回到方法上一层继续循环遍历下一个待创建的bean,这里我截个没有创建的bean的图来走下后面的创建流程:

    image.png

    图中所显示的bean我们发现从缓存中没有获取到,那我们继续跟踪代码来到:

    • 跟踪代码发下期间通过如下代码来检查bean 的定义信息是否在父BeanFactory中存在,如果存在的话,调用对应工厂Bean的方法去创建bean对象
     BeanFactory parentBeanFactory = this.getParentBeanFactory();
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }
    ...已省略.....
    
    • 通过下面的操作来标记当前bean已经被创建过了
    if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
    
    • 通过如下的操作来处理bean与bean之间依赖的问题
      • 1.首先获取当前bean的定义信息
    RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
    
    • 2.通过如下操作来先获取当前bean所依赖的其他bean组件,如果存在依赖的bean的话,通过getBean(...)进行依赖bean组件的创建
     RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;
    
                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
    
                        this.registerDependentBean(dep, beanName);
    
                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }
    
    • 接下来是真正的创建过程:
    this.createBean(beanName, mbd, args);
    

    继续跟踪代码来到AbstractAutowireCapableBeanFactory类中的#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法,具体来看如下分析:

    image.png

    其中上图中所示的是方法的参数 mbd参数为bean的定义的信息

    • 期间通过如下代码片段操作:
    beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
    

    通过方法#resolveBeforeInstantiation(beanName, mbdToUse)的拦截,让BeanPostProcessor【后置处理器】尝试着返回一个代理对象,继续跟踪代码来到:

    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = this.determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
    
            mbd.beforeInstantiationResolved = bean != null;
        }
    
        return bean;
    }
    
    • 首先在此方法中我们的InstantiationAwareBeanPostProcessor后置处理器先执行了

    • 接着进入if语句执行我们的

    bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    

    进去方法来到:

     protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        Iterator var3 = this.getBeanPostProcessors().iterator();
    
        while(var3.hasNext()) {
            BeanPostProcessor bp = (BeanPostProcessor)var3.next();
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
    
        return null;
    }
    

    获取所有的BeanPostProcessor接着遍历处理类型是InstantiationAwareBeanPostProcessor的后置处理器然后调用它的#postProcessBeforeInstantiation(...)方法具体去处理,至于处理的逻辑这里不在细看,继续跟踪代码来到:

      if (beanInstance != null) {
                return beanInstance;
            }
    

    如果没有获取代理对象,那么进行对象的真正创建过程:

    beanInstance = this.doCreateBean(beanName, mbdToUse, args);
    

    创建过程的细节,在上一篇中我们已经详细的说过了,这里不在累赘,其实到这里我们本篇的核心已经说完了,不知还记得开篇的那张类的依赖关系图,我们说了AnnotationAwareAspectJAutoProxyCreator实质是一个InstantiationAwareBeanPostProcessor类型的后置处理器,通过我们一步步的Dbug发现,在我们的每一个Bean的创建之前都会调用InstantiationAwareBeanPostProcessor类型的#postProcessBeforeInstantiation(...)方法进行相关的处理操作,既然知道了AnnotationAwareAspectJAutoProxyCreator的作用,那么在下节我们来分析#postProcessBeforeInstantiation(...)调用此方法具体做了什么?

    相关文章

      网友评论

          本文标题:AOP源码分析之AnnotationAwareAspectJAu

          本文链接:https://www.haomeiwen.com/subject/hmiiahtx.html