How do I manage dependencies using Java-based @Configuration classes?

In Spring, managing dependencies and configurations is commonly done using Java-based @Configuration classes. These classes allow you to define the beans and their dependencies programmatically. Here’s a step-by-step guide on how to manage dependencies with @Configuration classes:

1. Use the @Configuration Annotation

Mark your class with the @Configuration annotation. This tells Spring that the class defines one or more beans to be managed by the Spring container.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    // Define beans here
}

2. Define Beans with the @Bean Annotation

Within the @Configuration class, use the @Bean annotation to define individual beans. Methods annotated with @Bean will produce bean instances that will be managed by the container.

import org.springframework.context.annotation.Bean;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyService();
    }

    @Bean
    public MyRepository myRepository() {
        return new MyRepository();
    }
}

In this example, MyService and MyRepository will be registered as beans in the Spring context.

3. Inject Dependencies Between Beans

You can inject dependencies by passing other beans as method parameters. Spring resolves these dependencies automatically.

@Configuration
public class AppConfig {

    @Bean
    public MyRepository myRepository() {
        return new MyRepository();
    }

    @Bean
    public MyService myService(MyRepository myRepository) {
        return new MyService(myRepository);
    }
}

Here, MyService depends on MyRepository. Spring automatically resolves myRepository when creating the MyService bean.

4. Use @Primary for Bean Prioritization

If there are multiple beans of the same type, you can use the @Primary annotation to set the default bean to be used during injection.

@Configuration
public class AppConfig {

    @Bean
    @Primary
    public MyRepository mainRepository() {
        return new MyRepository();
    }

    @Bean
    public MyRepository backupRepository() {
        return new MyRepository();
    }
}

5. Use @Qualifier to Avoid Ambiguities

For cases where multiple beans of the same type exist but you don’t want to use the primary one, use the @Qualifier annotation along with the bean name.

@Bean("backupRepository")
public MyRepository createBackupRepository() {
    return new MyRepository();
}

Inject it as follows:

@Autowired
@Qualifier("backupRepository")
private MyRepository myRepository;

6. Leveraging Externalized Properties

You can link beans to properties defined in an application.properties file by using the @Value annotation or @ConfigurationProperties.

Using @Value:

@Configuration
public class AppConfig {

    @Value("${app.service.name}")
    private String serviceName;

    @Bean
    public MyService myService() {
        return new MyService(serviceName);
    }
}

7. Advance to Component Scanning (@Component)

Instead of manually defining @Bean methods, use annotations like @Component, @Service, @Repository, and @Controller for automatic bean detection, combined with @ComponentScan in the configuration. For example:

@Component
public class MyService {
    // Automatically registered
}

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // Automatically scans for annotated beans in the package
}

8. Conditional Bean Creation

Use annotations like @Conditional, @ConditionalOnProperty, or profiles (@Profile) to conditionally create beans based on environment or other properties.

By using @Configuration classes, you retain full control of your beans programmatically while keeping your project modular and easier to maintain.


Maven Dependencies

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.2.6</version>
</dependency>

Maven Central

How do I create my first Spring bean using XML configuration?

Creating your first Spring bean using XML configuration is a straightforward process. Here’s a step-by-step guide:


1. Add Spring Framework to Your Project

Make sure you have Spring dependencies added to your project. If you’re using Maven, include the following dependencies in your pom.xml:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.2.6</version> <!-- Update to a stable version -->
</dependency>

2. Create the Bean Class

Create a simple Java class that will serve as your Spring bean. For example:

HelloWorld.java

package com.example;

public class HelloWorld {
    private String message;

    public void setMessage(String message) { // Setter method for dependency injection
        this.message = message;
    }

    public void getMessage() {
        System.out.println("Your Message: " + message);
    }
}

3. Create the Spring XML Configuration File

Define the bean in an XML configuration file. Commonly, the file is named applicationContext.xml.

applicationContext.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">

    <!-- Definition of the HelloWorld bean -->
    <bean id="helloWorld" class="org.kodejava.spring.HelloWorld">
        <property name="message" value="Hello, Spring!"/>
    </bean>

</beans>

Here’s what’s happening:

  • id="helloWorld" specifies the name of the bean.
  • class="org.kodejava.spring.HelloWorld" points to the bean’s class.
  • The <property> tag is used to inject the value for the message property of the HelloWorld class.

4. Create the Main Class to Load the Bean

Write a Main class to load the Spring context and retrieve the bean:

MainApp.java

package org.kodejava.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        // Load the Spring configuration file
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");

        // Retrieve the bean from the Spring container
        HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");

        // Call bean method
        helloWorld.getMessage();
    }
}

5. Run the Application

When you run the MainApp class, you should see the output:

Your Message: Hello, Spring!

Key Points to Remember:

  • XML-based configuration is one of the older ways to configure Spring beans and is still supported, but newer versions prefer Java-based or annotation-based configuration.
  • Ensure the applicationContext.xml file is in the classpath (e.g., under src/main/resources).

That’s it! You’ve successfully created your first Spring bean using XML configuration.

How do I compile and execute a JDK preview features with Maven?

To compile and execute a JDK preview features with Maven, you need to add in the following configurations in your pom.xml file:

  • Compiler Plugin: The configuration should specify the JDK version and enable the preview features. It should look similar to this:
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <release>21</release>
                <compilerArgs>--enable-preview</compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>
  • Surefire Plugin: If you’re using the Maven Surefire Plugin to run your tests, you should also enable the preview features there. The configuration may look similar to this:
<build>
    <plugins>
    ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
            <configuration>
                <argLine>--enable-preview</argLine>
            </configuration>
        </plugin>
    </plugins>
</build>

Before building your project, ensure that you have JDK 21-preview installed on your computer, and it’s properly set in JAVA_HOME environment variable or in the IDE settings.

Then use Maven to package or install your project:

mvn clean package
# or
mvn clean install

Please ensure that you have the correct version of maven-compiler-plugin and maven-surefire-plugin that support the JDK 21-preview features. For the project that uses Spring MVC, you should make sure all dependencies are compatible with JDK 21-preview as well.

How to use Google Maven Central mirror?

The following configuration will use Google’s mirror of the Maven Central repository. Alter your ${M2_HOME}/conf/settings.xml or ${user.home}/.m2/settings.xml to add the mirror as seen in the following configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<settings>
    .
    .
    <mirrors>
        <mirror>
            <id>google-maven-central</id>
            <name>Google Maven Central</name>
            <url>https://maven-central.storage.googleapis.com</url>
            <mirrorOf>central</mirrorOf>
        </mirror>
    </mirrors>
    .
    .
</settings>

How to configure a proxy in Maven settings?

When we work behind a proxy server, we need to configure Maven to be able to connect to the internet. To enable proxy we can configure Maven settings.xml file, either in ${M2_HOME}/conf/settings.xml or ${user.home}/.m2/settings.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<settings>
    .
    .
    <proxies>
        <proxy>
            <id>my-proxy</id>
            <active>true</active>
            <protocol>http</protocol>
            <host>proxy.example.org</host>
            <port>8080</port>
            <username>username</username>
            <password>password</password>
            <nonProxyHosts>*.example.org|*.example.com</nonProxyHosts>
        </proxy>
    </proxies>
    .
    .
</settings>

The <proxy> element in the configuration above contains the information about the proxy server. These include information about the host, port, username and password. Set these elements to match your proxy server configuration.