Spring Field Injection with It's Drawbacks

Field injection is one of the methods provided by Spring for injecting dependencies. In this post, we will cover how to use field injection in Spring, and we will also discuss its drawbacks.

Field Injection Example

Field injection is done by annotating the fields with @Autowired. This tells the Spring framework to inject the dependencies directly into the fields. Here’s an example to demonstrate how field injection works.

Step 1: Create a Maven Project

Create a simple Maven project using your favourite IDE. Add the following dependencies to your pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.javaguides.spring</groupId>
    <artifactId>spring-field-injection-example</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.5</version>
        </dependency>
    </dependencies>
</project>

Step 2: Create the Service Classes

Create a simple service interface and its implementation.

package net.javaguides.spring.service;

public interface GreetingService {
    String greet();
}
package net.javaguides.spring.service;

import org.springframework.stereotype.Service;

@Service
public class GreetingServiceImpl implements GreetingService {
    @Override
    public String greet() {
        return "Hello, World!";
    }
}

Step 3: Create a Client Class

Create a client class that will use the GreetingService to print a greeting message. Use field injection to inject the GreetingService.

package net.javaguides.spring.client;

import net.javaguides.spring.service.GreetingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class GreetingClient {

    @Autowired
    private GreetingService greetingService;

    public void showGreeting() {
        System.out.println(greetingService.greet());
    }
}

Step 4: Create a Configuration Class

Create a configuration class to enable component scanning.

package net.javaguides.spring.config;

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

@Configuration
@ComponentScan(basePackages = "net.javaguides.spring")
public class AppConfig {
}

Step 5: Create the Main Application Class

Create the main application class to run the Spring application.

package net.javaguides.spring;

import net.javaguides.spring.client.GreetingClient;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        GreetingClient client = context.getBean(GreetingClient.class);
        client.showGreeting();
    }
}

Output

When you run the Application class, you should see the following output:

Hello, World!

Drawbacks of Field Injection

While field injection is simple and straightforward, it comes with several drawbacks:

  1. Testability: Field injection makes it difficult to write unit tests. Since the fields are private, you cannot easily inject mocks or stubs into the fields using reflection or setter methods.

  2. Immutability: It violates the principle of immutability. Dependencies can be changed at any time, which is not possible with constructor injection where dependencies are final.

  3. Encapsulation: It breaks encapsulation by making the fields visible to the framework, which goes against the principles of object-oriented programming.

  4. Circular Dependencies: Field injection can lead to circular dependencies, which are harder to detect and resolve compared to constructor injection.

  5. Dependency Visibility: Dependencies are not visible in the constructor, making it difficult to understand what dependencies the class has just by looking at it. This can make the code harder to read and maintain.

Conclusion

While field injection can be convenient for small applications and simple examples, it is generally recommended to use constructor injection or setter injection in real-world applications to avoid the drawbacks mentioned above. Constructor injection is particularly favored for its testability, immutability, and clear declaration of dependencies.

Comments