In our previous Articles we saw XML Based container configuration and Annotation based container configuration in detail. In this Article we are going to look at how Spring applications can be configured using Java classes and few annotations with a simple example.
Two main annotations on Java based container configuration in Spring are @Configuration
and @Bean
. We first look at the important key points on Each annotation first and then go for the simple working example.
@Configuration
@Configuration
is a Class level annotation- Its basic functionality is to Configure and assemble the bean objects that are defined with
@Bean
annotation. - Ex.,:
@Configuration
public class AppConfig {
@Bean
public VideoController controller() {
return new EnglishVideoImpl();
}
}
The above example is equivalent to the following XML Configuration:
<bean class=”net.geekcoders.EnglishVideoImpl”></bean>
- All the
@Bean
annotated methods will get instantiated in Spring IoC Container and referred from there for every call. Since, for Singleton scoped Bean only one time the object will get created and for other scopes their own life-cycle will be performed accordingly.
@Bean
@Bean
is a Method level annotation- Bean objects will register in ApplicationContext when a Method is annotated with
@Bean
. - Bean annotations refers to the method going to Instantiate, Configure and initializes a new bean in Spring IoC Container(ApplicationContext).
- We can use
@Bean
annotated method in@Configuration
annotated Class or@Component
annotated class. Mostly we use@Bean
in@Configuration
classes only. @Bean
is equivalent to<bean/>
tag in XML configuration.- Bean annotation supports various attributes provided by
<bean/>
tag. Those are init-method, destroy-method, autowiring and name.
Ex.,:
@Bean(name = "EnglishVideos", destroyMethod = "destroy", initMethod = "init", autowire = Autowire.BY_NAME)
public VideoManager EnglishVideoImpl() {
return new EnglishVideoImpl();
}
- From the example above, the Bean name will be “EnglishVideos”.If no name is declared in
@Bean
attribute, IoC Container will take method name as Bean name. - For Java Based container configuration, always use Direct class name as return type. You can also use the Object’s type as return type as like the above example(VideoManager is an Interface implemented by EnglishVideoImpl class).
- If you are using more than one Bean in the same context with the same type, then Spring will throw nouniquebeandefinitionexception. To avoid such exceptions you can use the name attribute in
@Bean
annotation and@Qualifier
annotation where you are injecting the dependency.
Ex.,:
@Bean
public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
VideoController controller = new VideoController();
controller.setEnglishVideos(englishVideos);
controller.setSpanishVideos(spanishVideos);
return controller;
}
- The above example uses
@Qualified
to avoid NONUNIQUEBEANDEFINITIONEXCEPTION and Setter-Based Dependency Injection.
- You can use any number of Parameters to the Bean method to Inject dependencies.
- Java Based Configuration supports both Setter-Based Dependency Injection and Constructor-Based Dependency Injection.
Constructor-Based Dependency Injection Example :
@Bean
public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
return new VideoController(englishVideos, spanishVideos);
}
Setter-Based Dependency Injection Example :
@Bean
public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
VideoController controller = new VideoController();
controller.setEnglishVideos(englishVideos);
controller.setSpanishVideos(spanishVideos);
return controller;
}
- You can add scope to the
@Bean
method by using@Scope
annotation as below.
@Bean(name = "EnglishVideos")
@Scope("prototype")
public VideoManager EnglishVideoImpl() {
return new EnglishVideoImpl();
}
Java-Based Container configuration in Spring Example :
I’m using Eclipse IDE, Java 8 and Spring 5.2.7 Libraries for this example.
Step 1 : Controller
Create VideoController class and copy below code.
package net.geekcoders.controllers;
import net.geekcoders.services.VideoManager;
public class VideoController {
private VideoManager englishVideos;
private VideoManager spanishVideos;
/**
* Method to get English and Spanish Language videos
*/
public void getAllVideos() {
System.out.println("getAllVideos :: Method to get English and Spanish Language Videos");
this.getEnglishVideos().listOfVideos();
this.getSpanishVideos().listOfVideos();
}
public VideoManager getEnglishVideos() {
return englishVideos;
}
public void setEnglishVideos(VideoManager englishVideos) {
this.englishVideos = englishVideos;
}
public VideoManager getSpanishVideos() {
return spanishVideos;
}
public void setSpanishVideos(VideoManager spanishVideos) {
this.spanishVideos = spanishVideos;
}
}
Step 2 : Interface
Now Create VideoManager Interface and copy below code.
package net.geekcoders.services;
import java.util.List;
public interface VideoManager {
List<String> listOfVideos();
}
Step 3 : Implementations
EnglishVideoImpl.java
package net.geekcoders.services;
import java.util.ArrayList;
import java.util.List;
public class EnglishVideoImpl implements VideoManager {
@Override
public List<String> listOfVideos() {
System.out.println("EnglishVideoImpl :: getting list of English Videos from DB/Files");
return new ArrayList<String>();
}
}
SpanishVideoImpl.java
package net.geekcoders.services;
import java.util.ArrayList;
import java.util.List;
public class SpanishVideoImpl implements VideoManager {
@Override
public List<String> listOfVideos() {
System.out.println("SpanishVideoImpl :: getting Spanish videos from DB/Files");
return new ArrayList<String>();
}
}
Step 4 : IoC Configuration with Java class
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import net.geekcoders.controllers.VideoController;
import net.geekcoders.services.EnglishVideoImpl;
import net.geekcoders.services.SpanishVideoImpl;
import net.geekcoders.services.VideoManager;
@Configuration
public class AppConfig {
public static void main(String[] args) {
System.out.println("AppConfig");
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
VideoController controller = applicationContext.getBean(VideoController.class);
controller.getAllVideos();
}
@Bean
public VideoController videoController(@Qualifier("EnglishVideos") VideoManager englishVideos, @Qualifier("SpanishVideos") VideoManager spanishVideos) {
VideoController controller = new VideoController();
controller.setEnglishVideos(englishVideos);
controller.setSpanishVideos(spanishVideos);
return controller;
}
@Bean(name = "EnglishVideos")
public VideoManager EnglishVideoImpl() {
return new EnglishVideoImpl();
}
@Bean(name = "SpanishVideos")
public VideoManager SpanishVideoImpl() {
return new SpanishVideoImpl();
}
}
- In the above AppConfig class, we have three Bean’s configured with @Bean annotation. @Configuration denotes that the AppConfig class is a Configuration class with Bean definitions.
- We have used Setter-Based Dependency Injection in this example code.
- When you run the above program from the AppConfig class you are able to see the below output in console.
- You can observe that, we have not used any one annotation or xml configuration other than AppConfig.java class to configure and run this example. This will help us to manage the application Bean’s and components in one single place.
That’s all for now on Spring Java Based Configuration with example…
Happy Reading!!!