Spring IOC and AOP Core Concepts Explained

IOC Section

1. Spring Ecosystem Overview

Spring is a comprehensive ecosystem providing essential infrastructure for Java application development. The Spring ecosystem typically consists of:

  • Spring Framework - the core framework
  • Spring Boot - adds auto-configuration capability, which reads Spring Boot Starter configuration during startup, initializes resources, and injects them into the Spring container
  • Spring MVC - web framework built on Spring Framework
  • Spring Cloud - distributed solution based on Spring Boot for microservices architecture

Spring is a lightweight, open-source framework featuring two core concepts: Inversion of Control (IOC) and Aspect-Oriented Programming (AOP).

2. Understanding Inversion of Control

Core Concept: Instead of creating objects manually via new, object creation is delegated to the Spring IOC container, which manages the entire lifecycle.

Benefits: Significantly reduces coupling between objects.

Implementation Details: The underlying mechanism combines XML configuration, reflection, and the simple factory pattern. Spring reads bean definitions (bean id and class path) from XML configuration files, uses reflection to instantiate objects, and exposes simple factory methods for retrieval.

3. Two IOC Implementations

Interface Characteristics Usage
BeanFactory Basic implementation, lazy loading (objects created only when requested) Rarely used directly by developers
ApplicationContext Extends BeanFactory, eager loading (objects created during container initialization) Primary interface for application development

ApplicationContext provides faster response times after startup, while BeanFactory offers slower startup but lower initial resource consumption.

4. Bean Management Approaches

Bean management involves two key operations: object creation and property injection (Dependency Injection).

XML-Based Configuration

Object Creation: Define beans in XML using <bean> element.

Property Injection:

  • Constructor injection
  • Setter injection
  • Can inject simple values or references to other beans
  • Supports nested beans and external beans

Annotation-Based Configuration

Object Creation Annotations:

@Component - generic component
@Service - service layer
@Repository - persistence layer
@Controller - web layer

Enable component scanning in XML:

<context:component-scan base-package="com.example"/>

Property Injection Annotations:

@Autowired - by type auto-wiring
@Qualifier - specify bean name for injection
@Resource - by name auto-wiring
@Value - inject simple values

5. Relationship Between DI and IOC

IOC defines the philosophy of delegating object creation to the container. DI (Dependency Injection) is the mechanism that implements IOC by using reflection to create objects and inject their dependencies. Essentially, IOC is the design principle, while DI is the concrete implementation technique.

6. Bean Scopes

  • singleton (default) - one instance per Spring container
  • prototype - new instance created each time the bean is requested
  • request - one instance per HTTP request (web-aware contexts only)
  • session - one instance per HTTP session (web-aware contexts only)

7. Singleton Thread Safety

Stateless beans (beans without mutable instance fields) are inherently thread-safe and should use singleton scope.

For stateful beans, singleton scope introduces thread safety concerns. Solutions include:

  • Using prototype scope
  • Using ThreadLocal variables to maintain thread-specific state within singleton beans

8. Spring Bean Lifecycle

The complete lifecycle consists of:

Instantiation → Property Population → Initialization → Destruction

Detailed phases:

  1. BeanFactoryPostProcessor - modifies bean definitions before instantiation
  2. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  3. Object Instantiation
  4. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
  5. Property Injection
  6. Aware Interface Callbacks:
    • BeanNameAware.setBeanName()
    • BeanFactoryAware.setBeanFactory()
    • ApplicationContextAware.setApplicationContext()
  7. BeanPostProcessor.postProcessBeforeInitialization()
  8. InitializingBean.afterPropertiesSet()
  9. Custom init method
  10. BeanPostProcessor.postProcessAfterInitialization()
  11. DisposableBean.destroy()
  12. Custom destroy method

9. Circular Dependency Resolution

Spring resolves circular dependencies using a three-level cache mechanism:

Cache Level Content Purpose
Level 1 (singletonObjects) Fully initialized singleton beans Final storage
Level 2 (earlySingletonObjects) Early reference to beans being instantiated Break circular references
Level 3 (singletonFactories) ObjectFactory for creating early references Support AOP proxy creation

Scenario 1 (No Circular Dependency): Use only Level 1 cache.

Scenario 2 (Circular Dependency Without AOP): Use Level 1 and Level 2 caches. The Level 2 cache holds semi-initialized beans temporarily.

Scenario 3 (Circular Dependency With AOP): All three levels are required. Level 3 stores factories that can generate proxy objects, enabling proper circular dependency resolution while maintaining AOP proxy functionality.


AOP Section

1. Aspect-Oriented Programming

AOP separates cross-cutting concerns from business logic, enabling:

  • Transaction management
  • Logging
  • Security checks
  • Other cross-cutting operations

This separation reduces code duplication and decreases coupling between business logic and infrastructure concerns.

2. Static vs Dynamic Proxy

Static Proxy

A proxy class is created at compile time, wrapping the target object. The proxy implements the same interface and can add behavior before/after method execution. Limitations include:

  • One proxy class per target class
  • Code must be modified when interfaces change

Dynamic Proxy

Proxy classes are generated at runtime.

JDK-Based Dynamic Proxy:

  • Requires target classes to implement interfaces
  • Uses java.lang.reflect.Proxy and InvocationHandler
  • Three parameters: class loader, interfaces, and InvocationHandler implementation

CGLIB Dynamic Proxy:

  • Works with classes without interfaces
  • Uses ASM library to modify bytecode and generate subclasses
  • Cannot proxy final classes or methods (final modifier prevents subclassing)
  • Implements MethodInterceptor interface

Comparison:

  • CGLIB: slower proxy creation, faster invocation
  • JDK Proxy: faster creation, slightly slower invocation
  • Spring defaults to JDK proxy but switches to CGLIB when classes don't implement interfaces

3. Design Patterns in Spring

Pattern Application
Simple Factory IOC container bean creation
Singleton Default bean scope
Dynamic Proxy AOP implementation
Template Method JdbcTemplate, RestTemplate
Observer ApplicationEvent mechanism

4. AOP Implementation

Key Terminology

  • Join Point: Methods that can be intercepted (execution point)
  • Pointcut: Actually intercepted methods (the subset of join points)
  • Advice: The additional logic to execute (your custom code)
  • Aspect: The combination of pointcut and advice (the weaving configuration)
  • Weaving: The process of applying advice to target methods

Advice Types

Type Annotation Timing
Before @Before Before method execution
After Returning @AfterReturning After successful method execution
After Throwing @AfterThrowing When exception occurs
After (Finally) @After Always after method execution
Around @Around Wraps method execution

Implementation Steps

Step 1: Add Maven Dependency

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.9</version>
</dependency>

Step 2: XML Configuration Approach

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
    <aop:config>
        <aop:pointcut id="servicePointcut" 
                      expression="execution(* com.example.service.*.*(..))"/>
        <aop:advisor advice-ref="loggingAdvice" pointcut-ref="servicePointcut"/>
    </aop:config>
</beans>

Step 3: Advice Implementation Class

public class LoggingAdvice implements 
        MethodBeforeAdvice, 
        AfterReturningAdvice, 
        MethodInterceptor {

    @Override
    public void before(Method method, Object[] args, Object target) {
        System.out.println("[BEFORE] Executing: " + method.getName());
    }

    @Override
    public void afterReturning(Object returnValue, Method method, 
                               Object[] args, Object target) {
        System.out.println("[AFTER] Completed: " + method.getName());
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("[AROUND-BEFORE] Method: " + 
            invocation.getMethod().getName());
        Object result = invocation.proceed();
        System.out.println("[AROUND-AFTER] Result processed");
        return result;
    }
}

Annotation Configuration Approach

Enable AspectJ Auto-Proxy:

<aop:aspectj-autoproxy/>

Aspect Class Implementation:

@Aspect
@Component
public class PerformanceMonitor {

    @Pointcut("execution(* com.example.service..*(..))")
    public void serviceMethods() {}

    @Before("serviceMethods()")
    public void preCheck(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[PRE] Entering method: " + methodName);
    }

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void postCheck(Object result) {
        System.out.println("[POST] Method returned: " + result);
    }

    @Around("serviceMethods()")
    public Object performanceTrack(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object outcome = pjp.proceed();
        long duration = System.currentTimeMillis() - startTime;
        System.out.println("[TIMING] Execution time: " + duration + "ms");
        return outcome;
    }
}

5. Spring Transaction Management

Programmatic Transaction Management

Direct use of TransactionTemplate or PlatformTransactionManager. Provides fine-grained control but introduces code coupling.

transactionTemplate.execute(status -> {
    // business logic
    return result;
});

Declarative Transaction Management

Uses AOP to wrap methods with transaction logic. Configuration is externalized and non-invasive to business code.

<tx:advice id="transactionAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="transfer*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

Or via annotation:

@Transactional(propagation = Propagation.REQUIRED)
public void transfer(Account from, Account to, BigDecimal amount) {
    // transfer logic
}

Comparison

Declarative approach is preferred for most scenarios due to its non-invasive nature. However, it operates at method granularity. For finer control (code-block level), programmatic management or method extraction refactoring is necessary.

6. Transaction Propagation Behaviors

Transaction propagation determines behavior when a transaction method calls another transaction method.

Propagation Behavior
REQUIRED (default) Joins existing transaction or creates new one
REQUIRES_NEW Always creates new transaction, suspends outer transaction
SUPPORTS Participates in transaction if exists, otherwise executes non-transactionally
NOT_SUPPORTED Executes non-transactionally, suspends outer transaction if exists
NEVER Executes non-transactionally, fails if transaction exists
MANDATORY Requires existing transaction, fails if none exists
NESTED Uses savepoints for nested transactions within outer transaction

The NESTED propagation allows partial rollback using savepoints—inner transaction failures don't necessarily roll back the outer transaction if the exception is caught and handled appropriately.

Tags: Spring IoC aop java Design Patterns

Posted on Mon, 13 Jul 2026 16:40:50 +0000 by s.eardley