April 11, 2022

Spring Java-based Configuration Example

In Spring XML Configuration Example we saw how configuration metadata is specified in XML that is used to register beans and wire dependencies. Spring framework also provides Java-based configuration to configure the Spring container, in this Spring Java-based configuration example we’ll see how that is done.

Spring Java-based configuration

Main annotations in Spring’s Java based configuration are @Configuration and @Bean.

  • @Configuration- Annotating a class with @Configuration indicates that this class is used as a source of bean definitions. Furthermore, @Configuration classes let inter-bean dependencies be defined by calling other @Bean methods in the same class.
  • @Bean- The @Bean annotation is used to indicate that a method instantiates, configures, and initializes a new object to be managed by the Spring IoC container. The @Bean annotation plays the same role as the element in the XML configuration. You can use @Bean-annotated methods with any Spring @Component. However, they are most often used with @Configuration beans.

For example following Java based configuration-

@Configuration
public class AppConfig {
  @Bean
  public OrderService orderService() {
    return new OrderServiceImpl();
  }
}

is equivalent to following XML configuration

<beans>
  <bean id="orderService" class="com.knpcode.service.OrderServiceImpl"/>
</beans>

Spring Java-based configuration example

In the example there is a class to place order called Order and purchase can be done from a store. Order and Store beans and bean dependencies will be configured using Java based configuration.

For this Spring Java based configuration example Maven build tool is used for managing dependencies. Please refer Create Java Project Using Maven in Eclipse to see how to create a Maven project.

Maven dependencies

For this example we need spring core and spring context dependencies. Spring Version used is 5.1.8 Release which is defined under properties element.

Spring core provides the basic framework classes and classes to interact with other modules.

Spring context module provides org.springframework.context.ApplicationContext interface which represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans.

<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>com.knpcode</groupId>
  <artifactId>SpringProject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>SpringProject</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <spring.version>5.1.8.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
      <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency> 
  </dependencies>
</project>
Bean classes
public interface OrderService {
  public void buyItems();
}
public class OrderServiceImpl implements OrderService {
  private IStore store;
	
  public IStore getStore() {
    return store;
  }
  public void setStore(IStore store) {
    this.store = store;
  }
  public void buyItems() {
    store.doPurchase();
  }
}
public interface IStore {
  public void doPurchase();
}
public class RetailStore implements IStore {
  public void doPurchase() {
    System.out.println("Doing purchase from Retail Store");
  }
}
Java configuration class
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.knpcode.springproject.service.IStore;
import com.knpcode.springproject.service.OrderService;
import com.knpcode.springproject.service.OrderServiceImpl;
import com.knpcode.springproject.service.RetailStore;

@Configuration
public class AppConfig {
  @Bean
  public OrderService orderService(){
    OrderServiceImpl orderService = new OrderServiceImpl();
    //setting bean dependency
    orderService.setStore(store());
    return orderService;
  }
	 
  @Bean
  public IStore store(){
    return new RetailStore(); 
  }
}

In the configuration class two beans are configured OrderService and Store. In the orderService dependency for store is also satisfied.

For running the application you can use the following class.

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import com.knpcode.springproject.model.Employee;
import com.knpcode.springproject.service.EmployeeService;
import com.knpcode.springproject.service.OrderService;
import com.knpcode.springproject.service.OrderServiceImpl;

public class App {
  public static void main( String[] args ){
    AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    OrderService orderService =  context.getBean("orderService", OrderService.class);
    orderService.buyItems();
    context.close();
  }
}
Output
17:40:49.318 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
17:40:50.243 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
17:40:50.251 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
17:40:50.255 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
17:40:50.271 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
17:40:50.291 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService'
17:40:50.399 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'store'
Doing purchase from Retail Store

Note that AnnotationConfigApplicationContext implementation of ApplicationContext is used here which accepts @Configuration classes as input.

Customizing Bean Name

By default, configuration classes use a @Bean method’s name as the name of the resulting bean that is why "orderService" is recognized as a bean name in the example. You can use name attribute to provide any other name. For example

@Configuration
public class AppConfig {
  @Bean(name = "myService")
  public OrderService orderService() {
    return new OrderServiceImpl();
  }
}

Spring Java Configuration with constructor dependency injection

In the above example setter dependency injection is used for setting bean dependency, following classes showcase constructor dependency injection.

Here is a modified OrderServiceImpl class with a constructor to initialize a Store.

public class OrderServiceImpl implements OrderService {
  private IStore store;
  public OrderServiceImpl(IStore store){
    this.store = store;
  }
  public void buyItems() {
    store.doPurchase();
  }
}
Modified Java config class.
@Configuration
public class AppConfig {
  @Bean
  public OrderService orderService(){
    // Bean dependency (Constructor)
    return new OrderServiceImpl(store());
  }
	 
  @Bean
  public IStore store(){
    return new RetailStore(); 
  }
}

That's all for the topic Spring Java-based Configuration Example. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment