Automatic injection into Map using SpringBoot factory mode

  • 2021-11-14 05:57:48
  • OfStack

Directory SpringBoot Factory Mode Auto Injection Map1. Build Factory Class 2. Two Implementation Classes 3. Injection into map, Test SpringBoot Auto Injection Principle 1. Auto Configuration Principle 2. Details

SpringBoot factory mode automatically injects Map

1. Create a factory class


public interface AnimalFactory {
   String food();
   String animal();
}

2. Two implementation classes


@Service
public class Cat implements AnimalFactory {
    @Override
    public String food(int type) {
        return " Eat fish ";
    }
    @Override
    public String animal(int type) {
        return " Cat ";
    }
}
@Service
public class Dog implements AnimalFactory {
    @Override
    public String food(int type) {
        return " Eat bones ";
    }
    @Override
    public String animal(int type) {
        return " Dog ";
    }
}

3. Inject it into map and test it


    @Autowired
    private Map<String, AnimalFactory> animalFactory;    
    public String factoryMode() {
        AnimalFactory animal = animalFactory.get("cat");
        return animal.animal() + animal.food();
    }

Output: Cats eat fish

Because the annotation used by the above two implementation classes is @ Service, key injected with animalFactory will automatically change the class names of Cat and Dog to lowercase, so animalFactory. get ("cat") is used.

(If you want to specify a name you can use @ Service ("XXX"), such as @ Service ("animalCat") on the Cat class and @ Service ("animalDog") on the Dog class, then key injected into animalFactory becomes animalCat and animalDog).)

In the above example, animalFactory. get ("cat") is directly used. When there are many animals, it is inconvenient to use enumeration class, 1 stands for cat, 2 stands for dog, and the front end passes in numbers, then obtains specific cat or dog through enumeration class through numbers, and then performs animalFactory. get (cat or dog)

Principle of SpringBoot Automatic Injection

1. Principle of automatic configuration

1) When SpringBoot is started, the main configuration class is loaded, and the automatic configuration function @ EnableAutoConfiguration is turned on

2), @ EnableAutoConfiguration function:

Import some components into the container using EnableAutoConfigurationImportSelector? You can view the contents of the selectImports () method;

List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

Get candidate configurations


SpringFactoriesLoader.loadFactoryNames()

Scan META-INF/spring. factories under all jar packet class paths

Wrap the contents of these scanned files into properties objects

Get the values for the EnableAutoConfiguration. class class (class name) from properties and add them to the container

Add all EnableAutoConfiguration values configured in META-INF/spring. factories under ClassPath to the container


# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

Each such xxxAutoConfiguration class is a component in the container and is added to the container; Use them for automatic configuration;

3) Carrying out automatic configuration function for each automatic configuration class;

4) Take * * HttpEncodingAutoConfiguration (Http encoding automatic configuration) * * as an example to explain the principle of automatic configuration;


@Configuration   // Indicates that this is 1 Configuration classes, previously written configuration files 1 Sample, you can also add components to the container 
@EnableConfigurationProperties(HttpEncodingProperties.class)  // Object of the specified class ConfigurationProperties Function; Combines the corresponding value in the configuration file with the HttpEncodingProperties Bind together; And put HttpEncodingProperties Join to ioc In a container 
@ConditionalOnWebApplication //Spring Bottom layer @Conditional Notes ( Spring Annotation version), according to different conditions, if the specified conditions are met, the configuration in the whole configuration class will take effect;      Determining whether the current application is web If yes, the current configuration class takes effect 
@ConditionalOnClass(CharacterEncodingFilter.class)  // Determine whether the current project has this class CharacterEncodingFilter ; SpringMVC Filter for garbled code resolution in; 
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)  // Determine whether a configuration exists in the configuration file   spring.http.encoding.enabled ; If it does not exist, the judgment is also valid 
// Even if we don't configure it in our configuration file pring.http.encoding.enabled=true , is also effective by default; 
public class HttpEncodingAutoConfiguration {
  
   // He has been with SpringBoot Maps the configuration file of 
   private final HttpEncodingProperties properties;
  
   // Only 1 In the case of a parameter constructor, the value of the parameter will be taken from the container 
   public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
  this.properties = properties;
 }
  
    @Bean   // Add to the container 1 Component, some values of which need to be derived from properties Get from 
 @ConditionalOnMissingBean(CharacterEncodingFilter.class) // Determine that the container does not have this component? 
 public CharacterEncodingFilter characterEncodingFilter() {
  CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
  filter.setEncoding(this.properties.getCharset().name());
  filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
  filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
  return filter;
 }

According to the current different conditions, decide whether this configuration class is effective or not.

1 But this configuration class takes effect; This configuration class adds various components to the container; The attributes of these components are obtained from the corresponding properties class, and every attribute in these classes is bound to the configuration file;

5) All the attributes that can be configured in the configuration file are encapsulated in the xxxxProperties class'; What can be configured in the configuration file can refer to this attribute class corresponding to a certain function


@ConfigurationProperties(prefix = "spring.http.encoding")  // Gets the specified value from the configuration file and bean To bind the properties of 
public class HttpEncodingProperties {
   public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

Essence:

1) The SpringBoot startup loads a large number of auto-configuration classes

2) Let's see if the function we need has the automatic configuration class written by SpringBoot by default;

3) Let's look at what components are configured in this auto-configuration class; (We don't need to configure any more as long as we have the components we want to use.)

4) When adding components to the automatic configuration class in the container, some attributes will be obtained from the properties class. We can specify the values of these attributes in the configuration file;

xxxxAutoConfigurartion: Automatically configure classes;

Add a component to a container

xxxxProperties: Encapsulates related properties in configuration files;

Step 2 Details

1. @ Conditional derivative annotation (Spring annotation version native @ Conditional function)

Function: The condition specified by @ Conditional must be established before adding components to the container and configuring all the contents inside to take effect;

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有1个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

Auto-configuration class can only take effect under the condition of 1;

How do we know which auto-configuration classes are in effect;

By enabling the debug=true property; To let the console print the auto-configuration report, so that we can easily know which auto-configuration classes are in effect;


=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches: Automatically configure class enabled 
-----------------
   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
        
    
Negative matches: (No Startup, No Matching Successful Auto Configuration Class) 
-----------------
   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
   AopAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.la

Related articles: