Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Core Concepts and Practical Usage of Spring Framework 6

Tech 1

Spring is a lightweight, open-source framework widely used in Java enterprise development. It encompasses both a foundational module—Spring Framework—and an extensive ecosystem known as the Spring technology stack.

Spring Framework vs. Spring Ecosystem

Spring Framework is the core library that provides essential features like Inversion of Control (IoC) and Aspect-Oriented Programming (AOP). It serves as the base for other Spring projects such as Spring Boot, Spring MVC, Spring Security, Spring Data, and Spring Cloud.

The broader Spring ecosystem includes all these subprojects, offering comprehensive solutions across cloud-native development, data access, security, microservices, and more.

Key Features of Spring Framework

  • Non-invasive: Domain models remain unaffected; only minimal annotations are needed on components.
  • Inversion of Control (IoC): Delegates object creation and dependency management to the framework.
  • Aspect-Oriented Programming (AOP): Modularizes cross-cutting concerns like logging, transactions, and security.
  • Container-based lifecycle management: Manages bean instantiation, configuration, and destruction.
  • Component-based architecture: Encourages building applications from reusable, well-defined components.
  • Comprehensive integration: Seamlessly works with numerous third-party libraries and frameworks.

Getting Started with Spring 6

Add the following dependencies to your pom.xml:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.9.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Basic Example

Define a simple class:

package com.example;

public class MessageService {
    public void printMessage() {
        System.out.println("Hello from Spring!");
    }
}

Configure it in beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="messageService" class="com.example.MessageService" />
</beans>

Use it in a test:

package com.example;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MessageServiceTest {
    @Test
    public void testMessageService() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        MessageService service = context.getBean("messageService", MessageService.class);
        service.printMessage();
    }
}

Dependency Injection (DI)

Spring supports two primary DI styles:

Setter Injection

<bean id="book" class="com.example.Book">
    <property name="title" value="Effective Java" />
    <property name="author" value="Joshua Bloch" />
</bean>

Constructor Injection

<bean id="book" class="com.example.Book">
    <constructor-arg name="title" value="Clean Code" />
    <constructor-arg name="author" value="Robert C. Martin" />
</bean>

Special values like null, XML entities (&lt;), and CDATA sections are also supported.

Managing Complex Dependencies

For object-type properties, use:

  • External bean reference: <property name="department" ref="deptBean" />
  • Inner bean: Define the dependent bean inline within the property.
  • Cascading assignment: Set nested properties like dept.name directly.

Collections (arrays, lists, maps) can be injected using <array>, <list>, and <map> tags.

Utility Schemas and Shortcuts

The util namespace allows defining reusable collections:

<util:list id="courseList">
    <value>Java</value>
    <value>Spring</value>
</util:list>

The p namespace simplifies property injection:

<bean id="student" class="com.example.Student"
      p:name="Alice" p:courses-ref="courseList" />

External Configuration

Load database properties from application.properties:

jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.user=root
jdbc.password=secret
jdbc.driver=com.mysql.cj.jdbc.Driver

Reference them in XML:

<context:property-placeholder location="classpath:application.properties" />

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.user}" />
    <property name="password" value="${jdbc.password}" />
    <property name="driverClassName" value="${jdbc.driver}" />
</bean>

Bean Scopes and Lifecycle

Beans are singleton by default. Other scopes include prototype, request, session, etc.

Lifecycle callbacks can be defined via init-method and destroy-method. Additionally, implement BeanPostProcessor for custom initialization logic.

FactoryBean

Use FactoryBean to encapsulate complex object creation:

public class CustomObjectFactory implements FactoryBean<MyObject> {
    @Override
    public MyObject getObject() throws Exception {
        return new MyObject(); // complex setup here
    }

    @Override
    public Class<?> getObjectType() {
        return MyObject.class;
    }
}

Annotation-Based Configuration

Enable component scanning:

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

Use stereotypes like @Component, @Service, @Repository, or @Controller to declare beans.

Inject dependencies with:

  • @Autowired: By type (supports constructor, field, setter injection).
  • @Qualifier: Resolve ambiguity when multiple beans of the same type exist.
  • @Resource (from Jakarta EE): Prefers name-based injection (byName), falls back to type.

Full Java Configuration

Replace XML with a @Configuration class:

@Configuration
@ComponentScan("com.example")
public class AppConfig {
}

Launch with:

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

Aspect-Oriented Programming (AOP)

AOP modularizes cross-cutting concerns. Key concepts:

  • Aspect: A class containing advice and pointcuts.
  • Join point: A specific point in execution (e.g., method call).
  • Pointcut: Expression that matches join points.
  • Advice: Action taken at a join point (before, after, around, etc.).

Annotation-Driven AOP

Enable with <aop:aspectj-autoproxy /> and define aspects:

@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint jp) {
        System.out.println("Calling: " + jp.getSignature());
    }
}

Reuse pointcuts with @Pointcut:

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

@Before("serviceMethods()")
public void logEntry(JoinPoint jp) { /* ... */ }

Set aspect precedence with @Order.

XML-Based AOP

<aop:config>
    <aop:aspect ref="loggingAspect">
        <aop:pointcut id="businessService"
            expression="execution(* com.example.service.*.*(..))" />
        <aop:before pointcut-ref="businessService" method="logBefore" />
    </aop:aspect>
</aop:config>

Testing with JUnit

JUnit 5

@SpringJUnitConfig(locations = "classpath:beans.xml")
public class ServiceTest {
    @Autowired
    private MyService service;

    @Test
    void testOperation() {
        assertNotNull(service);
    }
}

JUnit 4

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:beans.xml")
public class LegacyServiceTest {
    @Autowired
    private MyService service;

    @Test
    public void testLegacy() {
        // ...
    }
}

Transaction Management

Use @Transactional on service methods. Configure a transaction manager:

<bean id="txManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<tx:annotation-driven transaction-manager="txManager" />

Key attributes:

  • readOnly: Optimizes read-only operations.
  • timeout: Sets maximum execution time.
  • rollbackFor / noRollbackFor: Customize rollback behavior.
  • isolation: Controls concurrency effects (e.g., READ_COMMITTED).
  • propagation: Defines how transactions interact (e.g., REQUIRES_NEW).

Resource Abstraction

Spring’s Resource interface unifies access to files, classpath resources, URLs, etc.:

  • ClassPathResource: Loads from classpath.
  • FileSystemResource: Accesses local files.
  • UrlResource: Handles HTTP, FTP, file URLs.

Example:

Resource resource = new ClassPathResource("config/app.properties");
InputStream is = resource.getInputStream();

Ahead-of-Time (AOT) Compilation

Spring 6 supports AOT via GraalVM, enabling native image compilation for faster startup and lower memory usage—ideal for cloud-native environments. Unlike JIT (Just-In-Time), AOT compiles bytecode to native machine code during build time.

GraalVM’s Native Image tool produces standalone executables without requiring a JVM at runtime.

Validation Annotations

Common constraints include:

  • @NotNull, @NotEmpty, @NotBlank
  • @Min, @Max, @Size
  • @Email, @Pattern

These integrate with Spring’s validation infrastructure for robust input checking.

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.