spring boot #autowired filed injected with null in the #configuration class but worked with #import - spring

According to the reference using-boot-configuration-classes, I used #ComponentScan on the Application class and use the #Configuration on my config class, in my config class, I want to inject beans defined in other config class by using #Autowired annotation, but when I run the application, I got null for these fields, I tried to use import on the application and remove the #Configuration from config class, everything works fine.
Is it a bug of spring boot or I am misunderstanding about the usage of #Configuration annotation?

Are you trying to autowire other configuration classes into Application class?
Use a fresh method along with #PostConstruct to make it call automatically after Spring creates an instance of Application class.

Related

Is ApplicationContext automatically instantiated in Spring?

Is ApplicationContext automatically instantiated in Spring?
If I have my bean defined like this
#Component
public class Car{
...
}
and then I have my config class which tells Spring container where to look for beans through the annotation #ComponentScan
#Configuration
#ComponentScan
public class AppConfig {
...
}
Is Spring automatically creating a context loading all my beans? Or do I have to create it programmatically? If so how do I do it, with something like this?
#Configuration
#ComponentScan
public class AppConfig {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.getBean(Car.class);
...
}
Even doing this, there may be a problem, because every time I need the context I have to call new AnnotationConfigApplicationContext...
what is the recommended way to instantiate the context and making him available inside the whole project, maybe as a bean like inside Spring boot app where i can just autowire it.
How Spring Boot can initialize it, load all the beans and let the context available as a bean, ready to be autowired?
No, Application Context isn't automatically instantiated, if you're having a simple and basic Spring Core application. Moreover, your #Configuration class won't scan anything and won't create any beans, if you don't create your Spring Container/Context explicitly with that #Configuration class.
There are several ways of creating Application Context, but the most popular and traditional ones are:
ApplicationContext context = new ClassPathXmlApplicationContext(applicationContext.xml) - implying, that you have your container configuration in the applicationContext.xml file;
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigClass.class); - implying, that your ConfigClass is the #Configuration class.
However, if you have the Spring Boot application annotated with #SpringBootApplication, then the Application Context will be automatically instantiated for you, because:
#SpringBootApplication annotation consists of:
#EnableAutoConfiguration - which enables Spring Boot’s auto-configuration mechanism;
#ComponentScan - which enable #Component scan on the package where the application is located;
#Configuration - allows to register extra beans in the context or import additional configuration classes.
and this will spin up the context for you.
You can obtain the reference to the Spring Context created by Spring Boot, by the factory method you have in your main method: SpringApplication.run(MainClass.class, args);
This returns the reference to the Application Context and you can assign it to variable like this:
ApplicationContext context = SpringApplication.run(MainClass.class, args)

Using #PropertySouce in #Component

I tried to use #PropertySource in a #Component like:
#Component
#PropertySource("somepropertiesfile.properties")
public class Student {
...
}
It worked fine.
I want to understand, what is the different between using #PropertySource with #Component and #PropertySource with #Configuration.
Is there any difference or impact of using #PropertySource with #Component.
Configuration is itself a Component type, look into the #Configuration annotation implementation below.
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Configuration {
}
From API
Component: Indicates that an annotated class is a "component". Such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning.
Configuration: Indicates that a class declares one or more #Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.
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. These are same as Spring’s XML configuration. You can use #Bean annotated methods with any Spring #Component, however, they are most often used with #Configuration beans.
Here also you can use #PropertySource in #Component class but these are most suitable for #Configuration classes as it is a configuration related task.
You can refer Doc for detailed information.

How SpringBoot dependency injection works with different type of annotations

I recently started exploring Spring Boot. I see that there are 2 ways to define Beans in Spring Boot.
Define #Bean in the class annotated with #SprinBootApplication
Define #Bean in a class annotated with #Configuration
I am also confused about stereo-type annotation #Repository #Service #Controller etc.
Can someone please explain how dependency-injection works with these annotations?
Yes it is possible.
Either you use #Bean in any of your #Configuration or #SpringBootApplication class or mark the bean classes explicitly with annotations like #Service, #Component #Repository etc.
#Service or #Component
When you mark a class with #Service or #Compoenent and if spring's annotation scanning scope allows it to reach to the package, spring will register the instances of those classes as spring beans.
You can provide the packages to be included/excluded during scan with #ComponentScan
#Bean
#Beans are marked on factory methods which can create an instance of a particular class.
#Bean
public Account getAccount(){
return new DailyAccount();
}
Now in you application you can simply #Autowire Account and spring will internally call its factory method getAccount, which in turn returns an instance of DailyAccount.
There is a simple difference of using #Bean vs #Service or #Compoenent.
The first one makes your beans loosely coupled to each other.
In the #Bean, you have flexibility to change the account implementation without even changing any of the account classes.
Consider if your classes instantiation is a multi-step operation like read properties values etc then you can easily do it in your #Bean method.
#Bean also helps if you don't have source code access to the class you are trying to instantiate.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added.
You need to opt-in to auto-configuration by adding the #EnableAutoConfiguration or #SpringBootApplication annotations to one of your #Configuration classes.
You are free to use any of the standard Spring Framework techniques to define your beans and their injected dependencies. For simplicity, we often find that using #ComponentScan (to find your beans) and using #Autowired (to do constructor injection) works well.
One way is to define #Bean in the class annotated with
#SprinBootApplication
If you see #SprinBootApplication it is combination of many annotation, and one of them is #Configuration. So when you define #Bean in the Main class, it means it's inside #Configuration class.
According to Configuration docs :
Indicates that a class declares one or more #Bean methods and may be
processed by the Spring container to generate bean definitions and
service requests for those beans at runtime.
class annotated with #Configuration
When you define #Bean is a class annotated with #Configuration class, it means it is the part of spring configuration all the Beans define in it all available for Dependency-Injection.
I have also seen some code where neither of the 2 above approaches
have been used and yet dependency injection works fine. I have tried
to research a lot on this but could not find any concrete answer to
this. Is this possible?
I am assuming you are talking about Sterio-type annotation. Every sterio type annotation has #Component, according to docs :
Indicates that an annotated class is a "component". Such classes are
considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.

why do we need componentScan in spring

This question might be trivial but still i'm unable to find a good reason or best practice towards #ComponentScan in Spring
DI works just by self annotating the class then why do we need #ComponentScan
What is the best practice towards this?
#ComponentScan tells Spring in which packages you have annotated classes which should be managed by Spring.
Spring needs to know which packages contain spring beans, otherwise you would have to register each bean individually in(xml file). This is the use of #ComponentScan.
Take a simple example, you have a class and annotated with #Controller in a package package com.abc.xyz; , you have to tell the spring to scan this package for Controller class, if spring didn't scan this package, then spring will not identifies it as a controller class.
Suppose if your dealing with configuration file,
<context:component-scan base-package="com.abc.xyz">
like this,
When spring loads the xml file, this tag will search the all the classes present in the package com.abc.xyz, so any of the class containing #controller, #Repository #Service etc.., if it found then spring will register these annotated class in the bean factory.
Suppose if your using spring boot application,
Then your spring-boot application is annotated with The#SpringBootApplication.
#SpringBootApplication annotation is equivalent to using #Configuration, #EnableAutoConfiguration and #ComponentScan with their default attributes.
One more point if you didn;t specify the base package name in #ComponentScan,
it will scan from the package, where the #Springbootapplication present

Purpose of using #Configuration annotation

I have created a spring mvc based application but I didn't use this #Configuration annotation. What is the purpose of using #Configuration annotation? By using this, what are we communicating to springMVC container?
Assuming your application is using xml configuration rather than AnnotationConfig so it is not loaded to ApplicationContext at all.
#Configuration is used when ApplicationContext has been initialized and bean registration.
#Configuration annotation is a core Spring annotation, and not Spring MVC. It is a core entry point to configuring Spring-based application using Java config instead of XML config.
Please, use Spring Documentation more often because it is a place where you will find answers to most of your questions. Like this one:
Indicates that a class declares one or more Bean #Bean methods and may
be processed by the Spring container to generate bean definitions and
service requests for those beans at runtime

Resources