Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Architectural Fundamentals of Spring IOC and AOP

Tech May 8 4

The Spring Ecosystem and Framework Architecture

Spring is a comprehensive infrastructure for Java application development. While often used to refer to the Spring Framework, the ecosystem encompasses several specialized components:

  • Spring Framework: The core foundation providing IOC and AOP.
  • Spring Boot: Simplifies development through auto-configuration. It scans starter dependencies and initializes resources into the application context based on predefined conventions.
  • Spring MVC: A web framework built on the Servlet API.
  • Spring Cloud: Provides tools for building distributed systems and microservices.

Inversion of Control (IOC) and Dependency Injection

In traditional programming, objects manage their own dependencies by manually instantiating other objects. IOC shifts this responsibility to the Spring container. By managing object lifecycles centrally, Spring significantly reduces coupling between components.

Underlying Mechanisms

IOC is implemented using a combination of XML/Annotation configuration, Reflection API, and the Factory Pattern. The container reads class metadata, uses refleciton to instantiate objects, and manages them within a "factory" structure.

Core Container Interfaces

  1. BeanFactory: The most basic container providing fundamental dependancy injection. It uses lazy loading, meaning beans are instantiated only when requested.
  2. ApplicationContext: A sub-interface of BeanFactory that adds enterprise-specific functionality (such as internationalization and event propagation). It implements eager loading, instantiating singleton beans during startup for faster runtime response.

Bean Management and Scopes

Bean management involves instantiation and property injection (DI). This can be achieved through two primary methods:

  • XML Configuration: Defining beans in XML files and using <property> (setter injection) or <constructor-arg> (constructor injection).
  • Annotation-based Configuration: Using @Component, @Service, @Repository, or @Controller for discovery, and @Autowired or @Resource for injection.

Scopes and Thread Safety

  • singleton: (Default) One instance per Spring container. It is thread-safe only if the bean is stateles. For stateful singleton beans, ThreadLocal should be used to isolate data.
  • prototype: A new instance is created every time it is requested.
  • request/session: Instances tied to the lifecycle of an HTTP request or session.

The Bean Lifecycle

The lifecycle can be summarized into four high-level stages: Instantiation, Property Injection, Initialization, and Destruction. The granular steps are as follows:

  1. Instantiation: The container creates the bean instance.
  2. Populate Properties: Dependencies are injected via DI.
  3. Aware Interfaces: If the bean implements interfaces like BeanNameAware or ApplicationContextAware, the container sets the relevant infrastructure objects.
  4. BeanPostProcessor (Before): The postProcessBeforeInitialization method is triggered.
  5. Initialization: Custom initialization via @PostConstruct, InitializingBean.afterPropertiesSet(), or a custom init-method.
  6. BeanPostProcessor (After): The postProcessAfterInitialization method is triggered (often where AOP proxies are created).
  7. Destruction: When the container shuts down, methods marked with @PreDestroy or DisposableBean.destroy() are called.

Resolving Circular Dependencies

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

  1. singletonObjects (Level 1): Stores fully initialized beans.
  2. earlySingletonObjects (Level 2): Stores "half-finished" beans (instantiated but not fully injected).
  3. singletonFactories (Level 3): Stores ObjectFactories that can produce a bean (crucial for handling AOP-proxied beans during circular references).

Aspect-Oriented Programming (AOP)

AOP addresses cross-cutting concerns by separating business logic from systemic services like logging, security, and transaction management. This promotes code reuse and modularity.

Proxy Mechanisms

  • JDK Dynamic Proxy: Used when the target class implements an interface. It uses reflection to create a proxy class at runtime.
  • CGLIB: Used when the target class does not implement an interface. It generates a subclass of the target at the bytecode level. CGLIB cannot proxy final classes or methods.

AOP Terminology

  • Pointcut: An expression that defines which methods will be intercepted.
  • Advice: The logic executed at the Pointcut (e.g., @Before, @After, @Around).
  • Aspect: The combination of Pointcuts and Advices.

Implementation Example

Dependency requirement:

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

Defining an Aspect using annotations:

@Aspect
@Component
public class MonitoringAspect {

    @Pointcut("execution(* com.app.service.*.*(..))")
    public void serviceLayerMethods() {}

    @Around("serviceLayerMethods()")
    public Object trackPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        
        Object output = joinPoint.proceed();
        
        long duration = System.currentTimeMillis() - start;
        System.out.println(joinPoint.getSignature().getName() + " executed in " + duration + "ms");
        
        return output;
    }
}

Transaction Management and Propagation

Spring offers two types of transaction management:

  1. Programmatic: Using TransactionTemplate. Offers fine-grained control over specific code blocks.
  2. Declarative: Using @Transactional. Built on AOP, it manages transactions at the method level without polluting business logic.

Common Propagation Behaviors

  • REQUIRED: (Default) Joins an existing transaction or starts a new one if none exists.
  • REQUIRES_NEW: Always starts a new transaction, suspending any existing one.
  • SUPPORTS: Joins a transaction if one exists; otherwise, executes non-transactionally.
  • NESTED: Executes within a nested transaction using savepoints, allowing the sub-transaction to roll back independently of the outer one.
Tags: spring

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.