springBoot自动配置

本文详细介绍了Spring Boot中的自动配置原理,通过条件注解(@Conditional)实现不同环境下的Bean注入。文章列举了@ConditionalOnBean、@ConditionalOnMissingBean等条件注解的使用,并通过示例展示了如何根据系统环境(如Windows、Linux)选择性地注入Bean。同时,还探讨了自动配置的执行顺序和错误分析机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 自动配置步骤:

1 编写 Java config
	@Configuration
2 添加条件
	@Conditional
3.定位自动配置
	META-INF/spring.factories

二 条件注解大家庭
1.条件注解

@Conditional
@ConditionalSpring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。

在这里插入图片描述
参数是Condition类的集合看看Condition接口
在这里插入图片描述
matches就像正则的那个类一样…应该是true注入,false不注入
测试一下

1.创建一个person类
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Person {

    private String name;

    private int age;

}

2.配置类记得要扫到
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PersonConfigure {

    @Bean(name = "bill")
    @Conditional({WindowsCondition.class})
    public Person person1() {
        return new Person("Bill Gates", 62);
    }

    @Bean("linus")
    @Conditional({LinuxCondition.class})
    public Person person2() {
        return new Person("Linus", 48);
    }
}

3.然后测试一波,我这是springboot项目,测试比较简单.
import com.alibaba.fastjson.JSON;
import com.ql.servicetest.conditionDemo.Person;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.Map;

public class ConditionTest extends BaseTest implements ApplicationContextAware {

    @Test
    public void test1() {
        Map<String, Person> beansOfType = ApplicationContext.getBeansOfType(Person.class);
        String property = ApplicationContext.getEnvironment().getProperty("os.name");
        System.out.println("当前系统为:"+property);
        System.out.println(JSON.toJSONString(beansOfType));
    }

    public ApplicationContext ApplicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ApplicationContext = applicationContext;
    }
    }
    
 4. 我直接继承baseTest测试类,然后实现ApplicationContextAware得到spring容器,简单方便.一开始不加Conditional注解,就是两个都有,创建两个类LinuxCondition,WindowsCondition分别实现Condition接口,作为@Contional注解的值;
 import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition implements Condition {
 
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
 
        Environment environment = conditionContext.getEnvironment();
 
        String property = environment.getProperty("os.name");
        if (property.contains("Linux")){
            return true;
        }
        return false;
    }
}

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {
 
    /**
     * @param conditionContext:判断条件能使用的上下文环境
     * @param annotatedTypeMetadata:注解所在位置的注释信息
     * */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取ioc使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        //获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
 
        //获得当前系统名
        String property = environment.getProperty("os.name");
        //包含Windows则说明是windows系统,返回true
        if (property.contains("Windows")){
            return true;
        }
        return false;
    }
}
这两个类其实就是拿到当前运行环境进行判断,然后返回true,false.
分别将 @Conditional注解加上,然后运行:

5. 结论 只有条件为 true 是才会进行注入;

Bean注解

@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean

类注解

@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean@ConditionalOnsingleCandidate

属性注解

@ConditionalProperty
这个条件解释是: application.properties 或 application.yml 
文件中 mybean.enable 为 true 才会加载 MyCondition 这个 Bean,
如果没有匹配上也会加载,因为 matchIfMissing = true,默认值是 false

在这里插入图片描述
表达式注解

@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
如果我们有更复杂的多个配置属性一起判断,那么我们就可以用这个表达式了:

在这里插入图片描述

@ConditionalOnResource

如果我们要加载的 bean 依赖指定资源是否存在于 classpath 中,
那么我们就可以使用这个注解

在这里插入图片描述
看到这个 logback.xml 是不是很亲切,在我们引入第三方工具类如 Dozer 等都可以添加类似的开关

@ConditionalOnNotWebApplication(不是web应用)

@ConditionalOnSingleCandidate

自动配置的执行顺序

@AutoConfigureBefore
@AutoConfigureAfter
@AutoConfigureOrder

springBoot错误分析机制

FailureAnalysis 有三个组成部分
1. description 失败的一个描述
2. action 建议后续的一个动作
3. 失败时的异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值