To configure Beans in Spring

 

Getting into Spring Boot, part 8 To configure Beans in Spring

Of the Dependency Injection Container forms the heart of Spring. This can manage a variety of components, including Java Beans. The configuration of these Beans is time, and type-safe with the help of a Java class.

Companies

How to use Java Beans in Spring, explains this part of our tutorial.How to use Java Beans in Spring, explains this part of our tutorial.

In our example, the Bean to a Data base persister be, so a class that stores data in a database. Since it is in our hypothetical application, different types of storage, such as a File system persister or Cloud persister – could give the class implements the Interface Persister with the persist method:

public interface Persister {
public void persist();
}
public class DatabasePersister implements Persister {   @Override
public void persist() {
System.out.println("In DatabasePersister persist");
}
}

Configuration in the Java class

The Database Persistor is to be injected into another class, so the Container will be made known. This is done in a Java class, the Annotation @Configuration is characterized and, in General, to Config ends. Internally, this class is @Component characterized, and thus, the Component-Scanning found and evaluated:

@Configuration
public class PersisterConfig {
}

In the class the different Beans will be made by Bean definition methods with the Annotation @Bean marks:

@Configuration
public class PersisterConfig {
   @Bean
public Persister databasePersister() {
return new DatabasePersister();
}
}

Also possible configuration of components with the help of XML is now more common to find, but still often in existing projects.

Inject the Beans

One of such dimensions configured Bean can now be used with Autowired injected, for example, in a Service. The Service does not know ideally, the concrete Persistor, he works with the Interface and calls the defined persist-method:

@Service
public class PersisterService {
   @Autowired
private Persister persister;
   public void persistData() {
persister.persist();
}
}

The Container is now looking for when to Start the existing components to a Bean with the correct type, that is to say Persistorand the configured Data base persister. Through the implementation of the Interface, he is a Persister and is used as a candidate for injection.

In case of problems, it is sometimes helpful to the Beans in the Container to spend. The run method of the class Spring application in the Main class a The ApplicationContext back, access to the configured Beans or the name of the method getBeanDefinitionNames() allows you to:

@SpringBootApplication
public class DemoApplication {
   private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(DemoApplication.class, args);>
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
System.out.println(beanName);
}
}
}

In the console output, then we find, along with numerous other Beans, the configured Persister:

...persisterServicepersonControllerpersisterConfigdatabasePersister...

Spoilt for choice

It is exciting, if you pick up a second one Bean of the same Interface type in the configuration, such as the File system persister. He also implements Persister:

public class FilesystemPersister implements Persister {   @Override
public void persist() {
System.out.println("In FilesystemPersister persist");
}
}

The configuration in Persistent config is analogous to:

@Configuration
public class PersisterConfig {
   @Bean
public Persister databasePersister() {
return new DatabasePersister();
}
   @Bean
public Persister filesystemPersister() {
return new FilesystemPersister();
}
}

When Injecting the Bean in the Service of the Container is now faced with a Problem: Which of the two persistent goals, he should inject? Spring cannot solve the Dilemma alone. The application does not start and logs an error message:

Field persister in com.example.demo.PersisterService required a single bean, but 2 were found:
- databasePersister: defined by method 'databasePersister' in class path resource [com/example/demo/PersisterConfig.class]
- filesystemPersister: defined by method 'filesystemPersister' in class path resource [com/example/demo/PersisterConfig.class]

A solution to the Problem to be pleasing included in the message:

Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

With the help of the annotations @Primary or @Qualifier the conflict can be resolved. Annotation @Primary a(!) of the two Bean definition methods leads to the corresponding Bean is preferred. To do this, of course, the configuration class must be in the access. In the case of the use of third-party libraries, this is not always the case.

An Alternative is the Annotation is @Qualifierthat can be attached to the injection point, the user class. By specifying the method name is in the Persistent service the File system persister the preference given to:

@Service
public class PersisterService {
   @Qualifier("filesystemPersister")
@Autowired
private Persister persister;
   public void persistData() {
persister.persist();
}
}

In another class, however, perhaps the data base persister is preferred. You can find this pattern often when you configure multiple DataSources.

In the next part of the Spring Boot series, we look at the different ways to inject Beans. Spoiler: The used Field Injection is well-suited for Blog articles, but, in practice, only the second choice.

Ready to see us in action:

More To Explore

IWanta.tech
Logo
Enable registration in settings - general
Have any project in mind?

Contact us:

small_c_popup.png