The magic of SpringBoot autowiring

First,  the benefits of springBoot automatic configuration

  1. Recall that when you use spring to build a project, you need to write a lot of [xml] about spring . For example, the bean that reads the property configuration, the data source bean, the transaction management factory bean, the whole bean of mybatis and spring, and so on. When using this framework to build a project again, it is a cycle of operations.

But now when you use springBoot to build a project, you will find that all the configurations can be implemented for you without writing (you only need to configure when connecting to an external database, in fact, if you use the embedded database h2, you The application.properties configuration file is not required at all). You can use the @AutoWried @Resource annotation in your specific business code to inject data sources, transaction factories, etc. into the business layer, as if you configured it yourself.

  1. At this time, we will have a question, what exactly does springBoot do so that we can use those functional objects without configuration. In fact, springBoot uses the principle of automatic injection based on conditions, that is, when a certain condition is met, spring will instantiate the bean corresponding to the annotation and put it into the Srping context, so that you can use it easily. SpringBoot’s implementation of conditional configuration is inseparable from its core component @Conditional. Let’s slowly uncover the mystery of springBoot’s automatic configuration.

2. Introduction to @Conditional annotations

What the hell is @Conditional, don’t explain it, let’s take a small demo to get a general understanding

Describe the demo scenario: the Life entity bean is initialized by springBoot under certain conditions (@Conditional) and placed in the spring context.

1.1, Life entity class

/**
 * Dreams exist, life has meaning
 */ 
public  class  Life { 
    //work  
    private String work;
     //learning 
    private String study
     //love 
    private String love;

  // omitted seter /geter

}

1.2. Write our own conditional matching rules

/**
 * Implement ConfigurationCondition (this interface inherits Condition)
 */
public class MyTestConditional implements ConfigurationCondition {
    /**
     * Set the timing of using this class for parsing
     * 1. REGISTER_BEAN: Condition analysis will be performed when the Bean is registered
     * It is to judge the condition when the corresponding @Bean annotation and @condition annotation are used in combination
     *   @Bean annotation corresponds to the <bean/> tag of spring's xml
     * 2. PARSE_CONFIGURATION: Condition parsing will be performed when parsing @Configuration
     * It is to judge the condition when the corresponding @Configuration annotation and @condition annotation are used in combination
     *     The @Configuration annotation corresponds to the <beans/> tag of spring's xml
     * @return
     */
    @Override
    public ConfigurationPhase getConfigurationPhase() {
        return ConfigurationPhase.REGISTER_BEAN;
    }
    /**
     * This method is the core of conditional judgment. Only if the method returns true, it means that the condition is established, and the corresponding configuration is executed.
     * @param conditionContext
     * @param annotatedTypeMetadata
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, 
    AnnotatedTypeMetadata annotatedTypeMetadata)  {
               return  false ;   //Indicates that the verification fails 
    }

This class implements ConfigurationCondition and has the following two methods

1.  getConfigurationPhase() when the conditional rule works

2.  The matches() condition matching rule is here in order to demonstrate the processing without specific logical conditions

Returns a boolean value , if true, it means the condition is true and the _ configuration takes effect_

Otherwise, it will not take effect.

1.3, write our java instance bean automatic configuration

@Configuration 
//@Configuration is marked on the class, which is equivalent to using the class as <beans> in spring's xml configuration file, 
// The function is: configure the spring container (application context) 
public  class  ServerAutoConfiguration  {

    @Configuration   //<beans> in spring's xml configuration file 
    //Use this annotation to indicate that when springBoot starts, only if MyTestConditional.class is satisfied, the corresponding Life object will be generated 
    //that is, match() in MyTestConditional returns true @Bean Effective 
    @Conditional (MyTestConditional.class)
     public  static  class  StudentAutoConfiguration  {
         @Bean 
        public Life create ()  {
            System.out.println( "life start...." );
             return  new Life( "Work hard" , "Keep learning" , "Dare to love and hate" );
        }
    }
}

1.4, unit testing of springBoot

//Use Spring's unit test environment 
@RunWith (SpringRunner.class)
 //Load SpringBoot's context into unit tests 
@SpringBootTest (classes = AutoApplication.class)
 public  class  AutoApplicationTests  {
    //Inject springBoot's condition-based instantiation bean 
   @Autowired 
   private  Life life;
    @Test 
   public  void  showlife ()  {
      System.out.println( "The whole of life: " +life.toString());
   }
}

Start the springBoot project, no Life object is found in the console and Life cannot be injected in the unit test

After modifying the match() in MyTestConditional to return true, start again and the Life object is created

Also use SpringBoot’s unit tests to use the Life entity set up for us by springBoot

The entity creation process is as follows: When the springBoot project starts, all beans under @Configuration (xml configuration of srping) will be loaded, and when @Conditional(MyTestConditional.class) is encountered, the method’s Match will be called, and according to its return value To determine whether to instantiate all the classes annotated with @Bean @Import under the annotation

3. Customize a conditional configuration class / springBoot custom annotation

1. Simple explanation of @Condition annotation family

(1)、@Conditional

Official document definition:

“Indicates that a component is only eligible for registration when all specified conditions match”,

It means that a bean is created only after some list of conditions are met. and register it in the context of spring

(2), provided by SpringBoot

  • @ConditionalOnWebApplication The application must be a web application
  • @ConditionalOnMissingBean if there is no specified bean in the application context
  • @ConditionalOnBean If there is a specified bean in the application context
  • @ConditionalOnProperty(name,value) The bean under this annotation is loaded only if there is a configuration file with a value corresponding to the name      
  • @ConditionalOnCloudPlatform matches when in a cloud platform environment
  • @ConditionalOnClass If there is a specified bean in the classpath @ConditionalOnExpression If the corresponding expression is established, success
  • @ConditionalOnJava matches successfully based on the JVM version the application is running on
  • @ConditionalOnRepositoryType succeeds when a specific type of spring Data JPA is enabled
  • @ConditionalOnSingleCandidate When the bean corresponding to a specific class exists and is uniquely determined
  • @ConditionalOnJndi Find the condition made by JNDI
  • @Profile is triggered by a specific condition (production environment uses this configuration, non-production environment does not)
  • @ConditionalOnResource query from resource file
  • @ConditionalOnEnabledResourceChain Query from the resource chain
  • @ConditionalOnNotWebApplication This condition works if the application is not a web application
  • @ConditionalOnMissingClass If the corresponding class does not exist, create the corresponding bean

After the conditions are met, the class under the annotation will be loaded to work

(3) The so-called class under the action of the annotation works means:

These annotations are used in the following two ways

1. Acting on a class, all @Bean annotations under the class will work (the condition is true, the entity classes that load all @Beans under the annotation are stored in the spring context)

2. If it acts on the method, the corresponding @bean annotation under the method will work (if the condition is established, the entity class that uses @Bean under the annotation is loaded and stored in the spring context)

Used with @Configuration or @Bean, when used with @Configuration,

Then all @Bean methods or @Import or @ComponentScan under this class will be affected by its configuration conditions

@Configuration is equivalent to the tag of spring’s xml configuration file

The @Bean annotation is equivalent to the tag of spring’s xml configuration file

@Import(Xxx.class) injects the specified class instance into the spring context

@Configuration is marked on a class, which is equivalent to using the class as in spring’s xml configuration file, which is used to configure the spring container (application context)

For @Configuration, please refer to /duanxz/p/7493276.html

2. Custom Condition Annotation

Combine demo to set a custom annotation

(1), custom annotation

/*
  Custom Conditional Conditional Annotations
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(MyTestConditional.class)
public @interface ConditionalOnLife {
    Class<?>[] value() default {};
    String[] name() default {};}

(2), configure and use

@Configuration   //<beans> in spring's xml configuration file 
//Use this annotation to indicate that when springBoot starts, only if MyTestConditional.class is satisfied, the corresponding Life object will be generated 
//custom conditional annotation 
@ConditionalOnLife 
//@Conditional (MyTestConditional.class) 
public  static  class  DreamAutoConfiguration  {
     @Bean 
    public Dream createDream ()  {
         //life.toString(); 
        System.out.println( "dream start...." );
         return  new Dream();
    }
}

The background call successfully created the Dream entity and put it into the spring context

Leave a Comment

Your email address will not be published. Required fields are marked *