Java @Component class and @Configuration class wit

2019-09-07 14:10发布

问题:

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:

  1. AnnotationConfigApplicationContext class is accepting the java config class with @Configuration, without @Configuration and with @Component annotations, what is the difference between @Component and @Configuration?

  2. Why is it Accepting even without @Configuration annotation?

  3. When to use @Configuration, and when to use @Component as java config class?

回答1:

@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.



回答2:

@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.