Skip to content
Robin Drew edited this page May 26, 2025 · 16 revisions

Spring is a very large topic, so we will only be covering the essentials and hand-picked topics.

SpringBootApplication

@SpringBootApplication - A class annotated as an application should be defined as an entry point. The annotation includes:

  • @EnableAutoConfiguration - Enable the auto-configuration feature, a core part of Spring Boot.
  • @ComponentScan - Automatically scan this package and sub packages for components (configurable).
  • @Configuration - This class is a configuration and will automatically load any beans defined.

As with any entry point, a main method needs to be defined - in this case calling the SpringApplication run method.

@SpringBootApplication
public class WebServerApp {

   public static void main(String[] args) {
      SpringApplication.run(WebServerApp.class, args);
   }
}

Components

@Component - A class annotated as a component is automatically instantiated and registered as a bean if it is imported using @ComponentScan. Note that any parameters to the constructor selected will be injected by spring as if they were autowired, so need to be defined in a configuration.

There are a few special types of component:

  • @Configuration - Marks the class as part of the initialisation layer.
  • @Controller - Marks the class as part of the presentation layer.
  • @Repository - Marks the class as part of the persistence layer.
  • @Service - Marks the class as part of the service layer.

Controller

  • @Controller - A class annotated as a controller is a component where each annotated method responds to HTTP requests.
  • @RestController - A class annotated as a controller is a combination of @Controller and @RequestMapping
Annotation Description
@RequestMapping Specify the base url and content type
@GetMapping Alias for an HTTP GET request. This is used to lookup data. It should not contain a body.
@PostMapping Alias for an HTTP POST request. This is used to create data.
@PutMapping Alias for an HTTP PUT request. This is used to update data.
@DeleteMapping Alias for an HTTP DELETE request. This is used to delete data.
@PathVariable A parameter that represents a variable in the HTTP request path.
@RequestParam A parameter that represents a query parameter in the HTTP request.
@RequestHeader A parameter that represents a header from the HTTP request.
@CookieValue A parameter that represents a cookie from the HTTP request.
@RequestBody A parameter that represents the body of the HTTP request.
@RestController
@RequestMapping("/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {

    private List<User> users = new ArrayList<>();

    @GetMapping
    public List<User> getAllUsers() {
        return users;
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable int id) {
        Optional<User> user = users.stream().filter(u -> u.getId() == id).findFirst();
        return user.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<String> createUser(@RequestBody User user) {
        users.add(user);
        return ResponseEntity.ok("User created successfully");
    }

    @PutMapping("/{id}")
    public ResponseEntity<String> updateUser(@PathVariable int id, @RequestBody User updatedUser) {
        for (int i = 0; i < users.size(); i++) {
            if (users.get(i).getId() == id) {
                users.set(i, updatedUser);
                return ResponseEntity.ok("User updated successfully");
            }
        }
        return ResponseEntity.notFound().build();
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<String> deleteUser(@PathVariable int id) {
        if (users.removeIf(user -> user.getId() == id)) {
            return ResponseEntity.ok("User deleted successfully");
        }
        return ResponseEntity.notFound().build();
    }
}

Configurations

@Configuration - A class annotated as a configuration is used to define configuration for an aspect of the application. Configurations can be imported by the spring application and by each other using the @Import annotation.

The entire configuration can also be made optional, even if imported, using a conditional annotation.

Beans

@Bean - A method annotated as a bean will have its return value automatically registered as a spring bean. Note that any parameters to the method will be injected by spring as if they were autowired, so need to be defined in a configuration.

A bean can also be made optional using a conditional annotation.

Conditional Types

A bean or even an entire configuration can be optionally loaded, by using a conditional annotation. For example:

  • @ConditionalOnProperty - if a property is set to a specific value
  • @ConditionalOnExpression - if a spring expression evaluates to true
  • @ConditionalOnResource - if a resource exists
  • @ConditionalOnBean / @ConditionalOnMissingBean - if a bean has or has not been defined
  • @ConditionalOnClass / @ConditionalOnMissingClass - if a class is or is not on the classpath

Properties

When starting up an application, configuration properties are loaded from various sources (typically files). A simple way to load properties is to use the @Value to annotate fields and parameters.

public class UpdateManager {

   @Value("${app.update.frequency.amount}")
   private long amount;

   @Value("${app.update.frequency.unit}")
   private TimeUnit unit;
}

ConfigurationProperties

@ConfigurationProperties - A class annotated with this will be automatically instantiated and its fields populated directly as properties. This is the cleanest way to import properties and should be used in preference to @Value.

To import the properties so they are created as a bean, the @EnableConfigurationProperties annotation must be applied to a @Configuration.

// Read the properties 'app.update.frequency.amount' and 'app.update.frequency.unit'
@ConfigurationProperties("app.update.frequency")
public record UpdateFrequency(long amount, TimeUnit unit) {}


// Enable the properties to make then available as a bean
@Configuration
@EnableConfigurationProperties(UpdateFrequency.class)
public class UpdaterConfig {

   @Bean
   public UpdateManager updater(UpdateFrequency frequency) {
      return new UpdateManager(frequency.amount(), frequency.unit());
   }
}

Clone this wiki locally