zoukankan      html  css  js  c++  java
  • 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按条件控制,实现初始化,基本就不用自定义注解了。

  • 相关阅读:
    Object中的线程等待和Condition
    synchronized锁和Lock锁
    手写二叉排序树(二叉查找树、二叉搜索树)
    JDK源码之ArrayList-Iterator
    JDK源码之ArrayList
    Integer&int,自动装箱&自动拆箱
    学习Zookeeper第一课
    Thumbnailator处理图片
    线程的停止和中断
    BigInteger和BigDecimal
  • 原文地址:https://www.cnblogs.com/elnimo/p/13788602.html
Copyright © 2011-2022 走看看