NOTE

2.1 How the AnnotationAwareAspectJAutoProxyCreator Bean Instance Is Created

Class hierarchy, call-stack analysis, BeanFactoryAware setBeanFactory, registration and initialization of AnnotationAwareAspectJAutoProxyCreator

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Class Hierarchy

As shown below, AnnotationAwareAspectJAutoProxyCreator is both a Bean post-processor and a class that implements the BeanFactoryAware interface.

2. Analyze the Call Stack

First set breakpoints on the injected Calc and LogAspects classes and on the key methods shown above. After running, the call flow is as follows.

The breakpoints stop in sequence at:

  • BeanFactoryAware.setBeanFactory
    • org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory
      • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#setBeanFactory
      • org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#initBeanFactory
        • org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#initBeanFactory
  • BeanPostProcessor.postProcessBeforeInstantiation and postProcessAfterInitialization
    • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation
    • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInstantiation

3. First Study the Call Stack of BeanFactoryAware.setBeanFactory

It is as follows:

initBeanFactory:64, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
initBeanFactory:76, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
setBeanFactory:60, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
invokeAwareMethods:1648, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1617, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:553, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:481, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
registerBeanPostProcessors:225, PostProcessorRegistrationDelegate (org.springframework.context.support)
registerBeanPostProcessors:703, AbstractApplicationContext (org.springframework.context.support)
refresh:527, AbstractApplicationContext (org.springframework.context.support)
<init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:28, AopConfig (com.example.test.aop)

We trace line 12 and line 6 upward in sequence.

3.1. Register AnnotationAwareAspectJAutoProxyCreator

The key point is registerBeanPostProcessors:225, PostProcessorRegistrationDelegate (org.springframework.context.support).

It obtains the Bean class that was previously injected through @EnableAspectJAutoProxy, and then creates a Bean instance.

Therefore, so-called registration is actually the creation of a Bean instance.

  • registerBeanPostProcessors
public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    // First obtain the names of the classes that were registered into the container
    // and implement the BeanPostProcessor interface.
    // One of them is org.springframework.aop.config.internalAutoProxyCreator.
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);


    // Add other BeanPostProcessors to the container here.
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // Classify all BeanPostProcessors by priority.
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();

    for (String ppName : postProcessorNames) {
        // Those implementing PriorityOrdered go into internalPostProcessors.
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        // Those implementing Ordered go into orderedPostProcessorNames.
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        // Ordinary ones go into nonOrderedPostProcessorNames.
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First register BeanPostProcessors implementing PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // Then register BeanPostProcessors implementing Ordered.
    // org.springframework.aop.config.internalAutoProxyCreator is here.
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // So-called registration actually means creating the Bean instance.
    // If it exists in the container, obtain it from the container;
    // otherwise create it (AbstractAutowireCapableBeanFactory.doCreateBean).
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // Finally register ordinary BeanPostProcessors.
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // Finally, re-register all internal BeanPostProcessors.
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

3.2. Create the AnnotationAwareAspectJAutoProxyCreator Instance

Next we reach AbstractAutowireCapableBeanFactory.doCreateBean.

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // Create the Bean instance for the first time here.
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // Assign values to the Bean's properties.
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            // Initialize the Bean; this calls methods on Aware interfaces.
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

3.2.1. Initialize AnnotationAwareAspectJAutoProxyCreator

The logic above creates the Bean, assigns values to the Bean instance, and initializes the Bean:

initializeBean:1617, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)

  • initializeBean
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 {
        // Determine whether it implements an Aware interface; if so, call its method.
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // Call postProcessBeforeInitialization on all BeanPostProcessors.
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // Execute custom initialization methods such as @PostInit.
        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()) {
        // Call postProcessAfterInitialization on all BeanPostProcessors.
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}
3.2.1.1. If the Bean Is a BeanFactoryAware Type, Call setBeanFactory
  • invokeAwareMethods
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) {
            // org.springframework.aop.config.internalAutoProxyCreator implements AbstractAutowireCapableBeanFactory.
            // Inject the low-level AbstractAutowireCapableBeanFactory instance into the Bean currently being created.
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}
3.2.1.1.1. Inject the Low-Level AbstractAutowireCapableBeanFactory Instance into the Bean Being Created

Execution finally reaches:

setBeanFactory:55, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)

  • setBeanFactory
public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
    if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
        throw new IllegalArgumentException(
                "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
    }
    initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub