Spring component scan annotation and meta data - java

I'm actually studying spring application, more particularly the ComponentScan annotation that scans java packages to find some classes annotated with #Component.
I was wondering if the Spring ComponentScan annotation stores the related components found in other packages inside of the meta-datas of the Main Class (where I have the static void main method?)
Is this the only place where the framework stores these informations?

<context:component-scan base-package="com.mycompany.package" />
tells spring that it should look on com.mycompany.package and find classes annotated with the following (not only #Component ):
#Controller
#Repository
#Service
#Component
Then Spring will register these classes with the bean factory.
the Spring IoC container consumes a form of configuration metadata; this configuration metadata represents how you as an application developer tell the Spring container to instantiate, configure, and assemble the objects in your application.
Configuration metada are either an xml Configuration or java classes annotated with #Configuration that's where spring stores config informations.

Related

Getting Spring Boot to load annotated resources defined inside runtime dependencies

I am developing a bunch of Java/Sprint Boot webservices that will all have several identical (ideally, reusable) Spring-based resources:
many annotation-based Spring Security configurations
several #Services and #Components
many annotation-based event handlers
annotation-based exception handler
#ControllerAdvice that extends ResponseEntityExceptionHandler
annotation-based configuration files (#Configuration)
Ideally I could place these in a library (shared JAR file) and reuse them across the different webservice projects. However I don't believe Spring Boot will scan the entire dependency graph of libraries and load them based on their annotations.
Does anybody know of a way to encourage Spring Boot to do this? For example if I package the following class into a reusable/shareable library JAR:
#ControllerAdvice
#Slf4j
public class ApiExceptionHandler extends ResponseEntityExceptionHandler implements ApiContractConstants {
// ... common exception handling code to be used by
// all services
}
And then pull that in to a Spring Boot webservice (via Maven/Gradle) as a runtime dependency, how do I get Spring Boot to scan, find and load that exception handler for me?
The description makes me think of #SpringBootApplication. The property scanBasePackages of #SpringBootApplication defines base packages to scan for annotated components.
#SpringBootApplication(scanBasePackages = {"org.example"})

Auto-Configuration vs Auto-Wiring - Spring Boot

What is the difference between Spring Boot's auto-configuration and auto-wiring?
Is it that, autowiring is injection of a Bean into another class, and auto-configuration is the term used for complete auto-wired application?
Auto-configuration in Spring refers to what Spring does for you to configure your application based on the dependencies that you have added. Instead of having bean definitions and having to configure your own stuff in Spring MVC (Do you remember the amount of xml configs you had to do?), Spring Boot essentially "listens" for things on your class path, and if it's something that it's able to auto-configure for you, it'll do so.
The #SpringBootApplication annotation automatically opts you into having Spring automatically configure various beans for you.
You are correct in the sense that auto-wiring relates to Dependency Injection. Having the annotation #Autowired inside one of your classes, means that you bring an instance of the class that's being annotated, into the class that the annotation exists in.
● #SpringBootApplication
If you don’t want to use #SpringBootApplication, the #EnableAutoConfiguration and #ComponentScan annotations that it imports defines that behaviour so you can also use that instead.
#SpringBootApplication actually defines #EnableAutoConfiguration and #ComponentScan
● #EnableAutoConfiguration
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added
● #ComponentScan
All of your application components (#Component, #Service, #Repository, #Controller etc.) are automatically registered as Spring Beans.
● #Autowired is used for dependency injection

Spring Boot - What Annotations Are Needed

I am new to Spring Boot and I was just wondering if I need all annotations on my main method that I currently have
Here they are
#Import(ServiceConfiguration.class)
#SpringBootApplication(scanBasePackages = {"com.myproject.rest",})
#EnableJpaRepositories({"com.myproject.dao.jpa"})
#EntityScan(basePackages = "com.myproject.domain.jpa")
The class ServiceConfiguration.class has the following annotations
#Configuration
#EnableConfigurationProperties({SlackServiceProperties.class})
My database objects have the #Entity annotation, my rest classes have the #RestController annotation and my service classes have the #Component annotation
Just wondering are they all needed or can I exclude any of these annotations?
Thanks
If your main method is located in a top-level package, then all you need is:
#SpringBootApplication
It will automatically scan your sources recursively and pick up any #Bean's, #Component's or #Configuration's
Spring Data JPA will also automatically be configured if you're using this starter:
spring-boot-starter-data-jpa
If you structure your code like so:
com.myproject
- Application.java
com.myproject.configuration
- ServiceConfiguration.java
- OtherConfiguration.java
com.myproject.dao.jpa
- .. your repositories..
com.myproject.domain.jpa
- .. your #Entity classes...
You ONLY need to annotate your Application class with #SpringBootApplication.
All your #Configuration, repositories, other #Component and #Service classes will be auto scanned and configured by Spring Boot. That means you DON'T need to manually #Import configurations, you don't need #EnableJpaRepositories or #EntityScan.
All you need for Spring Boot to configure JPA is to include the JPA starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
You can follow this tutorial: https://spring.io/guides/gs/accessing-data-jpa/
You will see that it requires minimal annotations.
I assume it may depend on what you need, as I have not used a few of those in your example. I am not too familiar with all of Spring's "magic" when it comes to behind-the-scenes work it does with annotations. I have a perfectly functioning Spring Boot app with only
#SpringBootApplication
#Configuration
#ComponentScan
In order,
#SpringBootApplication is Spring's way of identifying that this application is from Spring Boot (one consequence, for example, is that there is no web.xml file).
#Configuration tells Spring to look for .properties files on your src path. Here, for example, you can define an "application.properties" file to define your datasource (database information for Spring to use).
#Component tells Spring to look for "Components" when it starts up the application. Pretty much #Controllers, #Service, etc. that may be found throughout your application.
For more accurate and in-depth explanations for many of Spring's annotations, may I direct you to:
http://www.techferry.com/articles/spring-annotations.html
and
https://dzone.com/refcardz/spring-annotations
These both have excellent descriptions and examples for the annotations.
Edit: #Configuration and #ComponentScan are included in #SpringBootApplication, as Strelok has pointed out in the comments.
Hope that helps.

How are the components scanned in spring boot

How does spring boot take care of component scan? We do not specify <component-scan> tag in spring boot in some web.xml file. We do not write any dispatcher servlet in spring boot. So where does spring boot do a component scan and how does it register all the controllers, services? What is the entry point for the spring boot web services micro-service? Note: Since it is a web-project I may not want to use the main method here.
There is an implicit one for the same package and sub-packages if you take a look at the annotation:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Inherited
#Configuration
#EnableAutoConfiguration
#ComponentScan
public #interface SpringBootApplication {...
Of course, it will be executed after the run method:
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
The question was: we do not specify component-scan and this is not true. It is declared in the Spring Boot annotation.
Edit 1: Spring MVC alternative
However, <component-scan> is a Spring annotation not just Spring Boot. You could configure your WAR web app with Spring MVC and you will not need Spring Boot libraries at all. Take a look at: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-config-customize
#Configuration
#EnableWebMvc
public class ConfigWebMVC extends WebMvcConfigurerAdapter
{
...
}
Additionally, for better understanding of #ComponentScan I would like to highlight some points of the documentation:
About bean lifecycle:
By default, ApplicationContext implementations eagerly create and
configure all singleton beans as part of the initialization process..
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-lazy-init
About Component scanning:
By default, classes annotated with #Component, #Repository, #Service,
#Controller, or a custom annotation that itself is annotated with
#Component are the only detected candidate components. However, you
can modify and extend this behavior simply by applying custom filters.
Add them as includeFilters or excludeFilters parameters of the
#ComponentScan annotation (or as include-filter or exclude-filter
sub-elements of the component-scan element)
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-scanning-filters

Where do those beans returned by Spring getBean method come from?

Could you please list all possible sources of getBean?
BTW, If I just write context.getBean(SomeInterface.class), can I get the implementation of the interface class?
They come from the Spring application context (which is what you are calling the getBean method on).
Spring has this concept of an application context, which is an object that contains things such as all the beans managed by Spring.
You put beans in the application context by configuring them in a Spring XML configuration file or by annotating classes with annotations such as #Component, #Service etc. and then letting Spring find them by scanning packages for those classes.
If you write context.getBean(SomeInterface.class) and there is a Spring bean that implements that interface, then that method call will return the bean that implements the interface.
These are basic concepts of the Spring framework. See chapter 5, The IoC Container in the Spring documentation for a detailed explanation of how it works.
If you go into the ApplicationContext class hierarchy, you will find that all spring Application Context file are child of org.springframework.core.io.DefaultResourceLoader class.
What DefaultResourceLoader does is it get the current thread context class loader(if none is provided). So we can understand that all application context file first load the classes defined. Application Context load all the beans defined in xml file, marked using #Bean annotation or other available spring annotations. Once the context scan through the annotation and/ or xml and load all the beans in the class loader. Context first create the dependencies and inject them in dependent.
To get context.getBean(SomeInterface.class), please refer below documentation.
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/context/support/AbstractApplicationContext.html#getBean(java.lang.Class)
As per my understanding of documentation, you shall get the bean if exact one implementation bean class is defined.

Categories