SpringBoot学习记录(2)

读取配置文件内容

  • @Value
@Value("${name}")
private String name;

@Value("${person.name}")
private String name2;
  • Environment
@Autowired
private Environment env;

System.out.println(env.getProperty("person.name"));
System.out.println(env.getProperty("address[0]"));
  • @ConfigurationProperties

创建对象与yml配置文件的内容进行绑定

@Component
@ConfigurationProperties(prefix = "person")
public class Person {

    private String name;
    private int age;
    private String[] address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String[] getAddress() {
        return address;
    }

    public void setAddress(String[] address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
person:
  name: zhangsan
  age: 20
  address:
    - beijing
    - shanghai

profile

在开发SpringBoot应用时,通常同一套程序会被安装到不同环境,比如开发、测试、生产等。不同环境下的配置不同,若每次打包时都要修改配置文件会非常麻烦。profile功能就是来进行动态配置切换的

  • profile配置方式

    • 多profile文件方式:提供多个配置文件,每个代表一个环境

      • application-dev.properties/yml 开发环境
      • application-test.properties/yml 测试环境
      • application-pro.properties/yml 生产环境
    • yml多文档方式

      • 在yml中使用 — 分隔不同配置
      ---
      server:
        port: 8081
      
      spring:
        profiles: dev
      ---
      server:
        port: 8082
      
      spring:
        profiles: test
      ---
      server:
        port: 8083
      
      spring:
        profiles: pro
      ---
      spring:
        profiles:
          active: dev
      
  • profile激活方式

    • 配置文件:在配置文件中配置
    spring.profiles.active=dev
    
    • 虚拟机参数:在VM options指定
    -Dspring.profiles.active=dev
    
    • 命令行参数
    java -jar xxx.jar --spring.profiles.active=dev
    

内部配置加载顺序

SpringBoot程序启动时,会从以下位置加载配置文件

  • file:./config/:当前项目的/config目录下
  • file:./:当前项目的根目录
  • classpath:/config/:classpath的/config目录
  • classpath:/:classpath的根目录

加载顺序为上文的排列顺序,高优先级配置的属性会生效

img

外部配置加载顺序

参考Springboot加载外部配置文件的方法_new defaultresourceloader().getresource-CSDN博客

SpringBoot原理分析

SpringBoot自动配置

Condition

通过Conditon这个功能,可以实现选择性的创建Bean操作

  • 自定义条件

    • 定义条件类:自定义类实现Condition接口,重写matches方法,在matches方法中进行逻辑判断,返回boolean值。以下为matches方法的两个参数

      • context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。具体来说,通过context对象,可以获取环境、IoC容器、ClassLoader对象等等
      • metadata:元数据对象,用于获取注解属性
      //获取注解属性值value
      Map<String, Object> map = 			 metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
      
    • 判断条件:在初始化Bean时,使用@Conditional(条件类.class)注解

  • SpringBoot提供的常用条件注解

    • ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
    • ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
    • ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
切换内置web服务器

SpringBoot的web环境中默认使用tomcat作为内置服务器,其实SpringBoot提供了4种内置服务器供选择,我们可以修改maven工程中的pom配置文件进行很方便的切换

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!--排除tomcat依赖-->
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>

    <!--引入jetty的依赖-->
<dependency>
    <artifactId>spring-boot-starter-jetty</artifactId>
    <groupId>org.springframework.boot</groupId>
</dependency>
@Enable*注解

SpringBoot提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。其底层原理是使用@Import注解导入一些配置类,实现动态加载

在一个工程中想使用其他工程定义的bean时,可以采用以下几种方法

  • 使用@ComponentScan扫描bean对应的包
@ComponentScan("com.itheima.config")
  • 使用@Import注解,加载类。这些类都会被Spring创建并放入IoC容器
@Import(UserConfig.class)
  • 可以对Import注解进行封装

自定义封装的EnableUser注解类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}

调用@EnableUser注解

@EnableUser
public class SpringbootEnableApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);

        Object user = context.getBean("user");
        System.out.println(user);

    }
}
@Import注解

@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IoC容器中。而@Import提供4种用法

  • 导入Bean

下面的代码直接导入Userbean

@Import(User.class)
public class SpringbootEnableApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);

        // 按类型获取,不能按名称获取,若使用按名称获取可能会找不到
        User user = context.getBean(User.class);
        System.out.println(user);

    }
}
  • 导入配置类
@Import(UserConfig.class)
public class SpringbootEnableApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);

		// UserConfig配置类中有两个bean:User和Role,均能被获取到
        User user = context.getBean(User.class);
        System.out.println(user);

        Role role = context.getBean(Role.class);
        System.out.println(role);
    }
}

对于这种导入方法,配置类UserConfig上面的注解@Configuration是可以省略的

//@Configuration
public class UserConfig {

    @Bean
    public User user() {
        return new User();
    }

    @Bean
    public Role role() {
        return new Role();
    }
}
  • 导入ImportSelector实现类,一般用于加载配置文件中的类

实现类如下

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 复写接口方法,导入两个bean:User和Role
        return new String[]{"com.itheima.domain.User", "com.itheima.domain.Role"};
    }
}

再导入实现类即可

@Import(MyImportSelector.class)
public class SpringbootEnableApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);

		// MyImportSelector实现类中有两个bean:User和Role,均能被获取到
        User user = context.getBean(User.class);
        System.out.println(user);

        Role role = context.getBean(Role.class);
        System.out.println(role);
    }
}

这种方式和上一种方式类似,但这种方式在配置实现类中是以字符串实现的,所以可以用这个方式加载一些配置文件的bean

  • 导入ImportBeanDefinitionRegistrar实现类

创建ImportBeanDefinitionRegistrar的实现类

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 获取User类的定义
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        // 注册以user为名称,User类的定义为定义的bean
        registry.registerBeanDefinition("user", beanDefinition);
    }
}

导入ImportBeanDefinitionRegistrar实现类

@Import({MyImportBeanDefinitionRegistrar.class})
public class SpringbootEnableApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);

		// ImportBeanDefinitionRegistrar中只有User的bean,没有Role的bean
        // 所以输出role时会报错
        User user = context.getBean(User.class);
        System.out.println(user);

        Role role = context.getBean(Role.class);
        System.out.println(role);
    }
}
@EnableAutoConfiguration注解
  • @EnableAutoConfiguration注解内部使用@Import(AutoConfigurationImportSelector.class)来加载配置类
  • 配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当SpringBoot应用启动时,会自动加载这些配置类,初始化bean
  • 并不是所有的bean都会被初始化,在配置类中使用Condition来加载满足条件的bean

说明:spring.factories是SpringBoot中用于自动配置的一种机制,位于META-INF目录下。spring.factories文件采用了 Java properties 文件的格式,每一行表示一个自动配置类及其对应的条件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YUKIPEDIA~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值