转载

springboot自动装配原理

springboot的自动装配在springboot autoconfigure子项目中完成。

@SpringBootApplication

从springboot 入口注解开始

@SpringBootApplication

点进去能看到有一个 @EnableAutoConfiguration 注解。

@EnableAutoConfiguration
public @interface SpringBootApplication

继续点击EnableAutoConfiguration注解。

@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

@Import注解引入了一个AutoConfigurationImportSelector类型的bean。继续点击AutoConfigurationImportSelector,进入之后找到方法getCandidateConfigurations().

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> 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;
    }

断言的意思:在META-INF/spring.factories下没发现配置类。配置类的配置是在META-INF/spring.factories文件下的。找到springboot autoconfigure 项目下的META-INF/spring.factories文件。

springboot自动装配原理

打开配置文件(贴部分自动装配的代码):这里需要自动装配的类配置。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=/
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration

到这里应该已经理解到一些了,spring将需要自动装配的类写在META-INF/spring.factories文件里面,再启动的时候去读取需要配置的类,并进行自动装配。

跟踪代码:loadFactoryNames方法

SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }

查看loadSpringFactories方法,贴个截图,正是去META-INF/spring.factories读取配置。

springboot自动装配原理

spring ioc加载之bean工厂后处理器的处理

回到getCandidateConfigurations方法,结合spring ioc的加载流程理解。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
        return configurations;
    }

找到debug模式下的调用流程图

springboot自动装配原理

refresh 》 处理bean工厂的后处理器 》 bean定义注册器后处理器 》 解析配置类 》 处理Import注解引入的AutoConfigurationImportSelector 》 读取META-INF/spring.factories下申明的配置类。

在bean定义扫描的时候,去META-INF/spring.factories这个文件里面读取需要自动装配的配置类,并将其添加到bean定义中。

在META-INF/spring.factories有申明redis自动装载,以redis为例讲一讲。

@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration

@Configuration注解,这个类是一个配置类

@EnableConfigurationProperties(RedisProperties.class) 引用RedisProperties这个属性类

再看RedisProperties这个类

@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {

@ConfigurationProperties(prefix = "spring.redis")这一行,spring.redis很熟悉,就是spring boot配置文件中对redis的配置,如果有就覆盖,没有就使用默认的参数配置。

自动装配的大致原理

以redis举例

先置条件

1.一个约定好的配置类RedisProperties。

2.一个配置类RedisAutoConfiguration,在配置类中以@Bean注解方式返回redistemplate

@Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

触发条件

3.@SpringBootApplication注解》@EnableAutoConfiguration》@Import(AutoConfigurationImportSelector.class)

4.spring加载ioc在处理bean工厂后处理器的步骤,解析配置类。处理

@Import注解。AutoConfigurationImportSelector实现了DeferredImportSelector接口,并且重写了selectImports。在selectImports调用了getCandidateConfigurations。getCandidateConfigurations完成加载自动加载配置类。返回,这个时候还是bean定义。

  1. 在bean定义转换为bean的时候,完成自动装配。
原文  https://segmentfault.com/a/1190000022619239
正文到此结束
Loading...