SpringBoot自动装配原理

1. Spring部分注解

  1. @Import : 为Spring容器中引入一些组件,通常都有无参数的构造方法
  2. @ConditionXXX : 需要达成某些条件该配置类才会生效
  3. @EnableAutoConfiguration : 开启自动配置注解,在@SpringBootApplication注解中已经开启

2. 自动装配过程

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
  1. 通过@Import(EnableAutoConfigurationImportSelector.class)引入了这个类
  2. 这个类的父类有一个selectImports的方法,这个方法里面有一个List configurations = getCandidateConfigurations(annotationMetadata,attributes);来获取到所有的候选配置
    protected List getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        /** 这个方法来获取所有的配置,getSpringFactoriesLoaderFactoryClass()方法是EnableAutoConfiguration.class; */
        List configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
        
        Assert.notEmpty(configurations,
                "No auto configuration classes found in META-INF/spring.factories. If you "
                        + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

  1. 再点进去
public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        try {
            /** 去扫描所有包的WEB-INF/spring.factory文件,得到他们的路径 */
            Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            List result = new ArrayList();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                /** 然后加载这个properties文件,获取到key为EnableAutoConfiguration.class的值,实际上就是很多的XXXAutoConfiguration配置类 */
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
                    "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }
  1. 加载这些配置类到Spring容器中,而这些配置类的作用,就是为容器中添加各种各样的组件,就完成了自动装配的作用,其中一个配置类如下:
@Configuration
/** 加载这个类到这个配置类中,是一些属性 */
@EnableConfigurationProperties(HttpEncodingProperties.class)
/** 必须是一个web项目才会加载这个配置类 */
@ConditionalOnWebApplication
@ConditionalOnClass(CharacterEncodingFilter.class)
/** 配置文件中有spring.http.encoding开头的也加载进来,如果没有匹配到,也可以加载这个类 */
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    private final HttpEncodingProperties properties;

    public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
        this.properties = properties;
    }

    /** @Bean,为容器中添加组件 */
    @Bean
    @ConditionalOnMissingBean(CharacterEncodingFilter.class)
    public CharacterEncodingFilter characterEncodingFilter() {

3 我们如何使用SpringBoot

  1. 添加 spring-boot-xxx-starter包
  2. 查看对应的AutoConfiguration配置类,和对应的xxxPropertise文件
  3. 如果不满意默认配置,我们就进行配置,按照他的规范
  4. 容器中有了对应的组件,我们还可以在自己的Confuration类中对这些组件进行进一步包装.

你可能感兴趣的:(SpringBoot自动装配原理)