Deep Dive into Spring IOC and AOP: Core Concepts, Lifecycle, and Code Walkthrough

This article explains Spring's IoC container architecture, bean definition processing, lifecycle methods, and AOP proxy creation, providing detailed code examples and step‑by‑step descriptions of resource loading, bean instantiation, dependency injection, and interceptor chains.

Thoughts on Knowledge and Action
Thoughts on Knowledge and Action
Thoughts on Knowledge and Action
Deep Dive into Spring IOC and AOP: Core Concepts, Lifecycle, and Code Walkthrough

IOC Core Concepts

Resource : abstraction of a resource (e.g., ClasspathResource, URLResource, FileSystemResource) that encapsulates access strategies.

BeanDefinition : holds all metadata of a bean such as class type, scope, lazy‑init flag, etc.

BeanDefinitionReader : converts external resource descriptions (XML, annotations) into internal BeanDefinition objects.

BeanFactory : the core container that stores a map of BeanDefinitions and creates/manages bean instances.

ApplicationContext : wraps a BeanFactory, adding extra features and integration with the external environment.

IOC Initialization Flow

Initialize the container.

Load bean definitions and register them in the BeanFactory.

Instantiate beans and perform dependency injection.

The refreshBeanFactory() method illustrates this process: it checks for an existing BeanFactory, destroys it if present, creates a new DefaultListableBeanFactory, customizes it, loads bean definitions, and finally assigns it to the context.

protected final void refreshBeanFactory() throws BeansException {
    if (this.hasBeanFactory()) {
        this.destroyBeans();
        this.closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = this.createBeanFactory();
        beanFactory.setSerializationId(this.getId());
        this.customizeBeanFactory(beanFactory);
        this.loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    } catch (IOException var2) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var2);
    }
}

Bean resource loading involves converting a resource file to an InputStream, parsing the XML source, and building a DOM object. Bean parsing then maps XML elements (Import, Alias, Bean, etc.) to BeanDefinition objects, which are stored in a HashMap for later lookup.

Bean Creation Process

Check the singleton cache; if the bean already exists, reuse it.

Verify the presence of a BeanDefinition in the current or parent factories.

Recursively resolve dependencies via getBean.

Instantiate using the appropriate constructor (default, autowired, or factory method).

The key methods are createBeanInstance and populateBean. The former resolves the bean class, handles instance suppliers, factory methods, and constructor selection. The latter performs property injection, applying autowire‑by‑name or autowire‑by‑type, invoking BeanPostProcessor s, performing dependency checks, and finally setting property values via reflection.

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { ... }
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { ... }

Property values are resolved in BeanDefinitionValueResolver.resolveValueIfNecessary and injected via bw.setPropertyValues, which uses reflection to call the appropriate setters.

AOP Core Concepts

Joinpoint : a method execution point.

Target Object : the original object being proxied.

Advice : code to run before, after, on exception, or around a joinpoint.

Interceptor : adapts advice to a MethodInterceptor implementation.

Proxy creation can use either JDK dynamic proxies (via InvocationHandler) or CGLIB (via ASM bytecode generation). Spring Boot registers AnnotationAwareAspectJAutoProxyCreator through AopAutoConfiguration, which is a BeanPostProcessor that transforms @Aspect beans into an Advisor collection.

static {
    APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
    APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
    APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}

The postProcessAfterInitialization method wraps beans with proxies when necessary, building an advisor list and creating either a JDK or CGLIB proxy:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

Proxy creation logic decides between JdkDynamicAopProxy and ObjenesisCglibAopProxy based on configuration flags and the target class type.

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
        return new JdkDynamicAopProxy(config);
    } else {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class");
        }
        return (!targetClass.isInterface() && !Proxy.isProxyClass(targetClass))
            ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config);
    }
}

During method execution, the proxy builds an ordered interceptor chain, then delegates to ReflectiveMethodInvocation.proceed(), which either calls the target method directly (if no interceptors) or walks through each MethodInterceptor (e.g., MethodBeforeAdviceInterceptor, AfterReturningAdviceInterceptor).

Overall AOP Workflow

Auto‑configure AnnotationAwareAspectJAutoProxyCreator as a bean post‑processor.

Convert all @Aspect beans into an Advisor collection.

For each matching bean, create a proxy (JDK or CGLIB) and register it.

When a proxied method is invoked, assemble the interceptor chain and execute it sequentially.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaProxyAOPIoCSpringDependencyInjectionbeanfactory
Thoughts on Knowledge and Action
Written by

Thoughts on Knowledge and Action

Travel together, with knowledge and action all the way

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.