Multiple ways to configure Spring

Core concepts

  • Bean: A bean is an object managed by the Spring IoC container
  • Bean Factory: A bean factory is a component that manages the lifecycle of beans, especially regarding the instantiation of new objects
  • Bean Definition: A bean definition is the set of properties given to the Spring container and that the requested bean will have, e.g., class, name, scope, dependencies, etc.
  • Context: A context is a bean factory with additional capabilities (mainly internationalization and event publishing)

Property file

john.(class)=ch.frankel.blog.Person       # 1
john.$0=John Doe # 2
jane.(class)=ch.frankel.blog.Person # 3
jane.$0=Jane Doe # 4
jane.$1(ref)=john # 5
  1. Define a new bean with name john and of class Person
  2. Set the single constructor argument to pass
  3. Define a new bean with name jane and of class Person
  4. Set the first constructor argument to pass
  5. Set the second constructor argument to give, the reference to john
var context = new GenericApplicationContext();                // 1
var factory = context.getDefaultListableBeanFactory(); // 2
var reader = new PropertiesBeanDefinitionReader(factory); // 3
var properties = new ClassPathResource("beans.properties"); // 4
reader.loadBeanDefinitions(properties); // 5
context.refresh(); // 6
  1. Create a new empty context
  2. Get its underlying bean factory
  3. Create a reader over the bean factory
  4. Get a handle on the above property file
  5. Parse the file to create bean definitions in the context
  6. Instantiate the beans from the beans definitions

XML

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="john" class="ch.frankel.blog.Person">
<constructor-arg value="John Doe" />
</bean>
<bean id="jane" class="ch.frankel.blog.Person">
<constructor-arg value="Jane Doe" />
<constructor-arg ref="john" />
</bean>
</beans>
var context = new ClassPathXmlApplicationContext("beans.xml");  // 1
  1. Create the application context, parse the XML file, create the bean definitions, and refresh the context!

Groovy DSL

import ch.frankel.blog.Personbeans {
john Person, 'John Doe'
jane Person, 'Jane Doe', john
}
var context = new GenericGroovyApplicationContext("beans.groovy");

Self-annotated classes

@Component                                              // 1
class John extends Person {
public John() {
super("John Doe");
}
}
@Component // 1
class Jane extends Person {
public Jane(John john) { // 2
super("Jane Doe", john);
}
}
  1. Mark the class for registration. Spring will instantiate a bean named after the class name, unqualified and uncapitalized
  2. Inject the bean of class John. Alternatively, we could inject by name by having the parameter @Qualifier("john") person. Note that since it's auto-wiring, we need to reduce the number of candidates to one, and there are two Person beans.
var context = new AnnotationConfigApplicationContext(John.class, Jane.class);

Configuration classes

  • Coupling with the framework
  • Confusing then bean with the class, and thus requiring subclassing when we need different instances of the same class
@Configuration                                                 // 1
public class AppConfiguration {
@Bean // 2
public Person john() {
return new Person("John Doe");
}
@Bean // 2
public Person jane(@Qualifier("john") Person person) { // 3
return new Person("Jane Doe", person);
}
}
  1. Mark the class as a configuration class
  2. The container will register the return value of this method as a bean
  3. As the context contains two Person beans, we need to inject by name
var context = new AnnotationConfigApplicationContext(ClassConfigurator.class);

Kotlin DSL

GenericApplicationContext().apply {             // 1
beans { // 2
bean("john") { // 3
Person("John Doe")
}
bean("jane") { // 3
Person("Jane Doe", ref("john")) // 4
}
}.initialize(this) // 5
refresh() // 6
}
  1. Instantiate a new context
  2. Create the bean definition DSL
  3. Define a named bean
  4. Inject the dependency by name
  5. Add the bean definitions to the context
  6. Instantiate the beans from the beans definitions

Bean definitions

public class PersonBeanD extends GenericBeanDefinition {    public PersonBeanDefinition(String name) {
this(name, null);
}
public PersonBeanDefinition(String name, String manager) {
setBeanClass(Person.class); // 1
var arguments = new ConstructorArgumentValues();
arguments.addGenericArgumentValue(name, "java.lang.String"); // 2
if (manager != null) {
arguments.addGenericArgumentValue(manager, "ch.frankel.blog.Person"); // 2
}
setConstructorArgumentValues(arguments); // 3
}
}
  1. Set the bean class
  2. Set the argument and its type
  3. Set the arguments
var context = new GenericApplicationContext();                  // 1
context.registerBeanDefinition("john", new PersonBeanD("John Doe")); // 2
context.registerBeanDefinition("jane", new PersonBeanD("Jane Doe", "john")); // 2
context.refresh(); // 3
  1. Create the context
  2. Register the bean definition
  3. Instantiate the beans from the beans definitions

Beans

var context = new GenericApplicationContext();
context.registerBean("john", Person.class, "John Doe");
context.registerBean("jane", Person.class, "Jane Doe", "john");
context.refresh();

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store