SpringBoot高级-自动配置原理剖析三

前言:通过前面两篇关于自动配置原理的剖析,我们可能对自动配置有一些了解,下面我们根据源码来具体研究SpringBoot中,是如何使用自动配置的。

一、找到IDEA目录中的External Libraries

二、继续找spring-boot-autoconfigure依赖

三、继续找到autoconfigure菜单下的注解类,这些注解我们都可以在自己的程序中使用

释义:

@ConditionalOnBean:当Bean存在时,才能在IOC容器中注入Bean;
@ConditionalOnClass:当类(字节码文件)存在时,才能在IOC容器中注入Bean;(与我们前面剖析中自定义的注解功能相同)
@ConditionalOnMissingBean:当Bean不存在时,才能在IOC容器中注入Bean;
@ConditionalOnMissingClass:当类(字节码文件)不存在时,才能在IOC容器中注入Bean;
@ConditionalOnProperty:当属性存在时,才能在IOC容器中注入Bean;
@ConditionalOnResource:当资源存在时,才能在IOC容器中注入Bean;

四、查看@ConditionalOnBean源码:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnBeanCondition.class})
public @interface ConditionalOnBean {
    Class<?>[] value() default {};

    String[] type() default {};

    Class<? extends Annotation>[] annotation() default {};

    String[] name() default {};

    SearchStrategy search() default SearchStrategy.ALL;

    Class<?>[] parameterizedContainer() default {};
}

五、查看RedisTemplate源码,了解redis实现自动配置的原理,在下图目录中查找(凡是源码文件名称是*AutoConfiguration.class的字节码文件,都是可以自动配置的类

六、查看源码,首先有一点需要知道,就是类上的注解与方法上的注解作用域不同,类上的注解适用于类所有的方法,比如RedisAutoConfiguration类上的@ConditionalOnClass(RedisOperations.class),而方法上的注解,只作用于该方法,比如RedisAutoConfiguration类的redisTemplate()方法上的@ConditionalOnMissingBean(name = "redisTemplate")

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

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

	@Bean
	@ConditionalOnMissingBean
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

}

@ConditionalOnClass(RedisOperations.class)注解就要求,首先IOC容器中必须存在RedisOperations这个字节码文件,才会在容器启动时,自动注入其声明的Bean(使用@Bean注解的方法,Bean的名称就是方法的名称,例如上面源码中声明的 redisTemplate 与 stringRedisTemplate),然后对于redisTemplate这个Bean能否自动初始化,还需要满足注解@ConditionalOnMissingBean(name = "redisTemplate")的要求,即:IOC容器中没有一个名称为redisTemplate的Bean,这样方可在容器启动的时候,初始化redisTemplate这个Bean。同理,stringRedisTemplate这个Bean的初始化策略。

针对SpringBoot提供的条件注解示例

一、@ConditionalOnProperty注解的使用,继续使用之前的代码,稍作修改,如下:

释义:自定义一个配置类(当程序启动时,配置类会自动加载),配置类在自动加载时,如果配置文件中,有一个属性名称是name,属性值为libai的属性存在,那么会在IOC容器中,自动将user2这个Bean初始化。

/**
 * @description:User配置类
 * @date: 2020/10/9 15:25
 * @author: winson
 */
@Configuration
public class UserConfig {
    @Bean
    @ConditionalOnProperty(name = "name", havingValue = "libai")
    public User user2() {
        return new User();
    }
}

二、测试类

@SpringBootApplication
public class SpringbootConditionApplication {

    public static void main(String[] args) {
        //启动SpringBoot的应用,返回Spring的IOC容器
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootConditionApplication.class, args);

        Object user2 = context.getBean("user2");
        System.out.println("user2=" + user2);
    }
}

三、测试结果如下,因为我现在并未在配置文件中加入相应属性

四、在配置文件中加入属性

name: libai

五、再测试,可以获取到user2这个Bean了

小结:通过上面的示例,我们在平常的使用时,就可以使用SpringBoot提供的那些注解,实现Bean按条件控制,实现初始化,基本就不用自定义注解了。

posted @ 2020-10-09 21:25  温森  阅读(173)  评论(0编辑  收藏  举报