• SpringBoot注解---2.组件赋值


    一、@Value

    1.作用范围

    @Value注解可以标注在字段、方法、参数以及注解上,而且在程序运行期间生效。

    2.用法

    通过@Value注解将外部的值动态注入到bean的属性中,一般有如下这几种情况:

    注入普通字符串

    @Value("NNN")
    private String name; // 注入普通字符串 

    注入操作系统属性

    @Value("#{systemProperties['os.name']}")
    private String systemPropertiesName; // 注入操作系统属性

    注入SpEL表达式结果

    @Value("#{ T(java.lang.Math).random() * 100.0 }")
    private double randomNumber; //注入SpEL表达式结果

    注入其他bean中属性的值

    @Value("#{person.name}")
    private String username; // 注入其他bean中属性的值,即注入person对象的name属性中的值

    注入文件资源

    @Value("classpath:/config.properties")
    private Resource resourceFile; // 注入文件资源

    注入URL资源

    @Value("http://www.baidu.com")
    private Resource url; // 注入URL资源
    

    3.@Value中#{···}和${···}的区别

    • #{...}:用于执行SpEl表达式,并将内容赋值给属性
    • ${...}:主要用于加载外部属性文件中的值
    • ${...}和#{...}:可以混合使用,但是必须#{}在外面,${}在里面
       说明  举例
    ${···}的用法 {}里面的内容必须符合SpEL表达式,通过@Value("${spelDefault.value}")我们可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,那么就会报错。不过,我们可以通过赋予默认值来解决这个问题。
    @Value("${author.name:meimeixia}")
    private String name;
    #{···}的用法 {}里面的内容同样也是必须符合SpEL表达式。例如,
    // SpEL:调用字符串Hello World的concat方法
    @Value("#{'Hello World'.concat('!')}")
    private String helloWorld;
    
    // SpEL:调用字符串的getBytes方法,然后再调用其length属性
    @Value("#{'Hello World'.bytes.length}")
    private String helloWorldBytes;
    混合使用
    // SpEL:传入一个字符串,根据","切分后插入列表中, #{}和${}配合使用时,注意不能反过来${}在外面,而#{}在里面
    @Value("#{'${server.name}'.split(',')}")
    private List<String> severs;

      上面片段的代码的执行顺序:通过${server.name}从属性文件中获取值并进行替换,然后就变成了执行SpEL表达式{'server1,server2,server3'.split(',')}

          在上文中#{}在外面,${}在里面可以执行成功,那么反过来是否可以呢?也就是说能否让${}在外面,#{}在里面,就像下面这样呢?

    // SpEL:注意不能反过来,${}在外面,而#{}在里面,因为这样会执行失败
    @Value("${#{'HelloWorld'.concat('_')}}")
    private List<String> severs2;
    

      答案是不能。因为Spring执行${}的时机要早于#{},当Spring执行外层的${}时,内部的#{}为空,所以会执行失败!

     

    二、@PropertySource加载配置文件

    1.作用

    从@PropertySource的源码中可以看出,我们可以通过@PropertySource注解指定多个properties文件,使用的形式如下所示。

    @PropertySource(value={"classpath:/person.properties", "classpath:/car.properties"})
    
    在@PropertySource注解的上面标注了如下的注解信息。这表示我们也可以使用@PropertySources注解来指定properties配置文件。
    @Repeatable(PropertySources.class)

    通过@PropertySource注解可以将properties配置文件中的key/value存储到Spring的Environment中,Environment接口提供了方法去读取配置文件中的值,参数是properties配置文件中定义的key值。当然了,也可以使用@Value注解用${}占位符为bean的属性注入值。

    2.使用注解方式获取值

    这里使用的@PropertySource(value={"classpath:/person.properties"})注解就相当于XML配置文件中使用的<context:property-placeholder location="classpath:person.properties" />。

    MainConfigOfPropertyValues Person
    package com.meimeixia.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    
    import com.meimeixia.bean.Person;
    
    // 使用@PropertySource读取外部配置文件中的key/value保存到运行的环境变量中,加载完外部的配置文件以后,使用${}取出配置文件中的值
    @PropertySource(value={"classpath:/person.properties"})
    @Configuration
    public class MainConfigOfPropertyValues {
    
    	@Bean
    	public Person person() {
    		return new Person();
    	}
    	
    }
    @Value("${person.nickName}")
    private String nickName; // 昵称

    3.使用Environment获取值

    使用@PropertySource注解读取外部配置文件中的key/value之后,是将其保存到运行的环境变量中了,所以我们也可以通过运行环境来获取外部配置文件中的值。

    IOCTest_PropertyValue 结果
    @Test
    public void test01() {
        printBeans(applicationContext);
        System.out.println("===================");
        
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);
        
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        String property = environment.getProperty("person.nickName");
        System.out.println(property);
        
        // 关闭容器
        applicationContext.close();
    }

    三、自动装配组件

    Spring组件的自动装配就是Spring利用依赖注入,也就是我们通常所说的DI,完成对IOC容器中各个组件的依赖关系赋值。

    1.@Autowired

    默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);

    如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找applicationContext.getBean("bookDao");

    @Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名

    自动装配默认一定要将属性赋值好,没有就会报错,可以使用@Autowired(required=false);

    @Primary:让spring进行自动装配的时候,默认使用首选的bean,也可以继续使用@Qualifier指定需要装配的bean的名字

    2.@Qualifier

    @Autowired是根据类型进行自动装配的,如果需要按名称进行装配,那么就需要配合@Qualifier注解来使用了。

    3.@Primary

    在Spring中使用注解时,常常会使用到@Autowired这个注解,它默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口而言,可能会有几种不同的实现类,而在默认只会采取其中一种实现的情况下,就可以使用@Primary注解来标注优先使用哪一个实现类。

    4.@Resource

    @Resource注解是Java规范里面的,也可以说它是JSR250规范里面定义的一个注解。该注解默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,那么默认取字段名将其作为组件的名称在IOC容器中进行查找,如果注解写在setter方法上,那么默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的一点是,如果name属性一旦指定,那么就只会按照名称进行装配。

    @Resource注解和@Autowired注解的功能是一样的,都能实现自动装配,只不过@Resource注解默认是按照组件名称(即属性的名称)进行装配的。虽然@Resource注解具备自动装配这一功能,但是它是不支持@Primary注解优先注入的功能的,而且也不能像@Autowired注解一样能添加required=false属性。

    5.@Inject

    @Inject注解也是Java规范里面的,也可以说它是JSR330规范里面定义的一个注解。该注解默认是根据参数名去寻找bean注入,支持Spring的@Primary注解优先注入,@Inject注解还可以增加@Named注解指定要注入的bean。

    @Inject注解和@Autowired注解的功能是一样的,都能实现自动装配,而且它俩都支持@Primary注解优先注入的功能。只不过,@Inject注解不能像@Autowired注解一样能添加required=false属性,因为它里面没啥属性。

    6.@Resource和@Inject俩注解与@Autowired注解的区别

    不同点

    1. @Autowired是Spring中的专有注解,而@Resource是Java中JSR250规范里面定义的一个注解,@Inject是Java中JSR330规范里面定义的一个注解
    2. @Autowired支持参数required=false,而@Resource和@Inject都不支持
    3. @Autowired和@Inject支持@Primary注解优先注入,而@Resource不支持
    4. @Autowired通过@Qualifier指定注入特定bean,@Resource可以通过参数name指定注入bean,而@Inject需要通过@Named注解指定注入bean

    相同点

    1. 三种注解都可以实现bean的自动装配。

    四、Profile

    在容器中如果存在同一类型的多个组件,那么可以使用@Profile注解标识要获取的是哪一个bean。也可以说@Profile注解是Spring为我们提供的可以根据当前环境,动态地激活和切换一系列组件的功能。这个功能在不同的环境使用不同的变量的情景下特别有用,例如,开发环境、测试环境、生产环境使用不同的数据源,在不改变代码的情况下,可以使用这个注解来动态地切换要连接的数据库。

    1. @Profile注解不仅可以标注在方法上,也可以标注在配置类上。
    2. 如果@Profile注解标注在配置类上,那么只有是在指定的环境的时候,整个配置类里面的所有配置才会生效。
    3. 如果一个bean上没有使用@Profile注解进行标注,那么这个bean在任何环境下都会被注册到IOC容器中,当然了,前提是在整个配置类生效的情况下。
  • 相关阅读:
    UiPath鼠标操作文本的介绍和使用
    UiPath鼠标操作元素的介绍和使用
    UiPath循环活动Do While的介绍和使用
    UiPath循环活动Do While的介绍和使用
    UiPath循环活动While的介绍和使用
    设计模式之: Decorator(装饰器)模式
    C语言深度解剖读书笔记(1.关键字的秘密)
    HDU 4341 Gold miner (分组背包)
    HDU 3496 Watch The Movie( 二维费用背包)
    Mahout源码MeanShiftCanopyDriver分析之一初识
  • 原文地址:https://www.cnblogs.com/nxf-rabbit75/p/14619864.html
Copyright © 2020-2023  润新知