Derik Lima's Blog

How to Start a Java Project with Spring using Annotations

By Derik Lima on Mar 30, 2020

In the previous post we’ve implemented a simple example making use of Spring IoC (Inversion of Control) and DI (Dependency Injection) through xml configuration. In this one, we implement the same example, but this time, with Spring annotations instead of XML.

The complete source code is available on my github on the following link.

Creating the project

First step is to use the maven command-line to actually create the project:

mvn archetype:generate
	-DgroupId={project-packaging}
	-DartifactId={project-name}
	-DarchetypeArtifactId=maven-archetype-quickstart
	-DinteractiveMode=false

In my case, I’d go for something like:

mvn archetype:generate
	-DgroupId=com.deriklima
	-DartifactId=spring-annotation-demo
	-DarchetypeArtifactId=maven-archetype-quickstart
	-DinteractiveMode=false

After maven is done bootstrapping your project, you can open it with an IDE of your preference.

Setting maven to compile with Java 8

Let’s set maven to compile our project using Java 8.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

Adding the Spring dependency

In order to use Spring’s IoC and DI, you only need one dependency (Actually it’s more as spring-context brings spring-core and others, but you get the point).

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

The basic boilerplate

As we’re going to use the annotation approach, we need to create a Config Class. You can name it whatever you want. I’m gonna go for something very original: SpringConfig

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

@Configuration
public class SpringConfig {}

Then, on App.java, you can load this configuration file with the following:

import com.deriklima.springannotationdemo.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {
  public static void main(String[] args) {
    try (AnnotationConfigApplicationContext context =
        new AnnotationConfigApplicationContext(SpringConfig.class)) {

        }
  }
}

I’m using a try-with-resources here because the Spring context needs to be closed.

Loading a bean

The rest is pretty much the same as the previous post about configuring Spring with XML annotations.

Let’s create a class named UserService that will just return a random User id:

public class UserService {

  private SecureRandom random;

  public UserService() {
    random = new SecureRandom();
  }

  public String getCurrentUser() {
    return "User " + random.ints(1, 100).findFirst().getAsInt();
  }
}

Now, we need to declare this bean on SpringConfig

import com.deriklima.springannotationdemo.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

  @Bean
  public UserService userService() {
    return new UserService();
  }

}

Finally, we can get an instance of this bean on our App class

import com.deriklima.springannotationdemo.config.SpringConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

  public static void main(String[] args) {

    try (AnnotationConfigApplicationContext context =
        new AnnotationConfigApplicationContext(SpringConfig.class)) {

      UserService userService = context.getBean("userService", UserService.class);

      System.out.println(userService.getCurrentUser());
      System.out.println(userService.save("Test User"));
    }

  }
}

And that’s it! You’ve successfully used Spring IoC (Inversion of Control) as you’ve delegated the instantiation of your object to Spring. But this time, using annotations instead of xml configuration.

Adding dependencies to beans

Now, like the example on the previous blog post, let’s suppose UserService needs to expose a method to persist a user and therefore needs access to UserDAO, how can you ask Spring to inject that specific dependency for you?

Simple, let’s first create a mocked version of UserDAO with a save method:

import java.security.SecureRandom;

public class UserDAO {

  private SecureRandom secureRandom;

  public UserDAO() {
    secureRandom = new SecureRandom();
  }

  public Integer save(String user) {
    return secureRandom.ints(1, 100).findFirst().getAsInt();
  }

}

Then we do a few things:

  • Create constructor in UserService that receives a UserDAO as a parameter and assigns it to an instance of UserDAO
  • Create the save method that receives a String as a parameter and returns an Integer which would be the User ID in this case.

Notice that I’m not really implementing a User class here just for the sake of simplicity, so a String is used instead.

import java.security.SecureRandom;

public class UserService {

  private SecureRandom random;
  private UserDAO userDAO;

  public UserService(UserDAO userDAO) {
    random = new SecureRandom();
    this.userDAO = userDAO;
  }

  public String getCurrentUser() {
    return "User " + random.nextInt(10);
  }

  public Integer save(String user) {
    return userDAO.save(user);
  }
}

And last but not least, we need to add this new bean (UserDAO) to SpringConfig and tell Spring to inject this new instance in UserService for us.

import com.deriklima.springannotationdemo.UserDAO;
import com.deriklima.springannotationdemo.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.deriklima")
public class SpringConfig {

  @Bean
  public UserDAO userDAO() {
    return new UserDAO();
  }

  @Bean
  public UserService userService() {
    return new UserService(userDAO());
  }
}

Congratulations again! You’ve successfully used the Spring DI (Dependency Injection)! This time using Annotations instead of XML.

Like stated before, the name is very self-explanatory, but you’ve delegated the instantiation and construction of UserService to Spring and Spring automagically inject UserDAO for you.

Things can get more interesting if you make use of Interfaces instead of implementations, but the scope of this post is just to show you how to use Spring with XML.

If something is not working for you, you can check out the complete source code on my github on the following link.
Hope it helps!

© Copyright 2024 by Derik Lima.