Where DI comes into play - For example, now in sort algorithm we are using BubbleSort, and if we want to change to QuickSort it can be done with very little code change in spring framework.

"When you annotate (@Configuration, @Component, @Controller, @RestController etc..)the classes in spring it creates the beans and stored in application context. Using @Autowired, spring injects references of the objects in the class with @Autowired annotation. "

if BubbleSort implements Sort, QuickSort implements Sort and we have used

@Autowired
Sort s; then spring doesn't know which bean to inject
then use 
(solution 1)
Sort s;
public void methodName(Sort quickSort){ this.s = quickSort;}
(solution 2) 
use @Primary on class level.
(solution 3)
use @Qualifier annotation.

lets say in application.properties file there is 
app.value.username = "Velma". use 
@Value(${app.value.username}") 
private String username; 
Spring will inject the username - Velma into username attribute.

How to Configure Beans - how to put objects into application context.

Using annotations @Controller, @Service, @Repository, @Configuration, @SpringBootApplication on classes - spring creates objects(beans)  and put in to application context.

"If we don't want to create beans using annotations or 
if we don't have source code to annotate then we should/ can
 create a configuration class." for example

@Configuration
public class RestConfig{
@Bean
public Sort quickSort(){
return new QuickSort(); - lets say value = 10001
}
@Bean
public Sort bubbleSort(){
quicksort(); value is also 10001
return new BubbleSort();
}

NOTE: "Return value of bean in configuration class is cache", 
where as for others like component it is not cached value is
different for Component classes.