I know springs AnnotationConfigApplicationContext
is capable of accepting not only @Configuration
classes as input but also plain @Component
classes and classes annotated with JSR-330 metadata.
I have created AppConfig.java below without @Configuration annotation.
public class AppConfig {
@Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
Passed this class as my java config class to AnnotationConfigApplicationContext
, it accepted and registered my service beans.
I did some modification on above same AppConfig like below.
@Component
public class AppConfig {
@Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
passed AppConfig to AnnotationConfigApplicationContext, it accepted and registered my service beans.
Question:
AnnotationConfigApplicationContext
class is accepting the java config class with @Configuration
, without @Configuration
and with @Component annotations, what is the difference between @Component
and @Configuration
?
Why is it Accepting even without @Configuration
annotation?
When to use @Configuration
, and when to use @Component as java config class?
@Component
Indicates that an annotated class is a "component".
That is, in a context where component scanning is enabled, Spring generates bean definitions for @Component
annotated types. These bean definitions end up being turned into beans.
@Configuration
, which is itself annotated with
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, [...]
So any @Configuration
type, for which Spring generates a bean, acts as a factory for beans.
The javadoc of @Bean
states
@Bean
methods may also be declared within classes that are not
annotated with @Configuration
. For example, bean methods may be
declared in a @Component
class or even in a plain old class. In such
cases, a @Bean
method will get processed in a so-called 'lite' mode.
Bean methods in lite mode will be treated as plain factory methods by
the container (similar to factory-method declarations in XML), with
scoping and lifecycle callbacks properly applied. The containing class
remains unmodified in this case, and there are no unusual constraints
for the containing class or the factory methods.
In contrast to the semantics for bean methods in @Configuration
classes, 'inter-bean references' are not supported in lite mode.
Instead, when one @Bean
-method invokes another @Bean
-method in lite
mode, the invocation is a standard Java method invocation; Spring does
not intercept the invocation via a CGLIB proxy. This is analogous to
inter-@Transactional
method calls where in proxy mode, Spring does not
intercept the invocation — Spring does so only in AspectJ mode.
So @Bean
methods have full functionality in @Configuration
annotated classes and limited functionality in @Component
annotated classes.
why it is Accepting even without @Configuration annotation?
That's how the class is designed. An ApplicationContext
is a BeanFactory
. AnnotationConfigApplicationContext
simply offers an extra way to register a bean definition.
When to use @Configuration, and when to use @Component as java config class?
These really completely separate goals. Follow the javadoc. When you need to setup an ApplicationContext
, you can use an AnnotationConfigApplicationContext
with a @Configuration
annotated class. If you simply need a bean, annotate its type with @Component
.
@Component annotation marks the Java class as a bean, but @Configuration annotation marks the Java class containing beans (methods that have @Bean annotation).
The @Bean annotation must use with @Configuration exactly to create Spring
beans.
In following class
@Component
public class AppConfig {
@Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
@Bean annotation is not any effect, and getSampleService() method will be plain old java method and will not be singleton, because as i mentioned, @Bean annotation must use with @Configuration, so it must be repaired as following:
@Configuration
public class AppConfig {
@Bean(name="sampleService")
public SampleService getSampleService(){
return new SampleService();
}
}
so replacing @Configuration annotation with any other annotation, or removing it, just make @Bean annotation ineffective and getSampleService() method will not be singleton anymore.