【Spring注解驱动开发】如何使用@Value注解为bean的属性赋值,我们一起吊打面试官!

@Value(“#{systemProperties[‘os.name’]}”)

private String systemPropertiesName; // 注入操作系统属性

  • 注入表达式结果

@Value(“#{ T(java.lang.Math).random() * 100.0 }”)

private double randomNumber; //注入表达式结果

  • 注入其他Bean属性

@Value(“#{person.name}”)

private String name; // 注入其他Bean属性:注入person对象的属性name

  • 注入文件资源

@Value(“classpath:io/mykit/spring/config/config.properties”)

private Resource resourceFile; // 注入文件资源

  • 注入URL资源

@Value(“http://www.baidu.com”)

private Resource url; // 注入URL资源

2.通过配置文件注入属性的情况

通过@Value(“${app.name}”)语法将属性文件的值注入到bean的属性中,如下所示。

@Component

// 引入外部配置文件组:${app.configinject}的值来自config.properties。

// 如果相同

@PropertySource({“classpath:io/mykit/spring/config/config.properties”,

“classpath:io/mykit/spring/config/config_${anotherfile.configinject}.properties”})

public class ConfigurationFileInject{

// 这里的值来自application.properties,spring boot启动时默认加载此文件

@Value(“${app.name}”)

private String appName;

// 注入第一个配置外部文件属性

@Value(“${book.name}”)

private String bookName;

// 注入第二个配置外部文件属性

@Value(“${book.name.placeholder}”)

private String bookNamePlaceholder;

// 注入环境变量对象,存储注入的属性值

@Autowired

private Environment env;

public String toString(){

StringBuilder sb = new StringBuilder();

sb.append(“bookName=”).append(bookName).append(“\r\n”)

.append(“bookNamePlaceholder=”).append(bookNamePlaceholder).append(“\r\n”)

.append(“appName=”).append(appName).append(“\r\n”)

.append(“env=”).append(env).append(“\r\n”)

// 从eniroment中获取属性值

.append(“env=”).append(env.getProperty(“book.name.placeholder”)).append(“\r\n”);

return sb.toString();

}

}

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

我们这里提供一个测试属性文件:advance_value_inject.properties,大致的内容如下所示。

server.name=server1,server2,server3

author.name=binghe

测试类AdvanceValueInject:引入advance_value_inject.properties文件,作为属性的注入

@Component

@PropertySource({“classpath:io/mykit/spring/config/advance_value_inject.properties”})

public class AdvanceValueInject {

}

${…}的用法

{}里面的内容必须符合SpEL表达式, 通过@Value(“${spelDefault.value}”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如下所示。

@Value(“${author.name:binghe}”)

上述代码的含义表示向bean的属性中注入配置文件中的author.name属性的值,如果配置文件中没有author.name属性,则向bean的属性中注入默认值binghe。例如下面的代码片段。

@Value(“${author.name:binghe}”)

private String name;

#{…}的用法

// SpEL:调用字符串Hello World的concat方法

@Value(“#{‘Hello World’.concat(‘!’)}”)

private String helloWorld;

// SpEL: 调用字符串的getBytes方法,然后调用length属性

@Value(“#{‘Hello World’.bytes.length}”)

private String helloWorldbytes;

${…}和#{…}混合使用

${...}和#{...}可以混合使用,如下文代码执行顺序:通过${server.name}从属性文件中获取值并进行替换,然后就变成了 执行SpEL表达式{‘server1,server2,server3’.split(‘,’)}。

// SpEL: 传入一个字符串,根据","切分后插入列表中, #{}和 配置使用 ( 注意单引号,注意不能反过来 {}配置使用(注意单引号,注意不能反过来 配置使用(注意单引号,注意不能反过来{}在外面,#{}在里面)

@Value(“#{‘${server.name}’.split(‘,’)}”)

private List servers;

在上文中#{}在外面,${}在里面可以执行成功,那么反过来是否可以呢?也就是说能否让${}在外面,#{}在里面,如下代码所示。

// SpEL: 注意不能反过来${}在外面,#{}在里面,这个会执行失败

@Value(“${#{‘HelloWorld’.concat(‘_’)}}”)

private List servers2;

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

@Value注解用法小结:

  • #{…} 用于执行SpEl表达式,并将内容赋值给属性。

  • ${…} 主要用于加载外部属性文件中的值。

  • #{…} 和${…} 可以混合使用,但是必须#{}外面,${}在里面。

@Value注解案例


这里,我们还是以一个小案例的形式来说明。

首先,我们来创建一个Person类作为测试的bean组件,如下所示。

package io.mykit.spring.plugins.register.bean;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

import lombok.ToString;

import java.io.Serializable;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试实体类

*/

@Data

@ToString

@NoArgsConstructor

@AllArgsConstructor

public class Person implements Serializable {

private static final long serialVersionUID = 7387479910468805194L;

private String name;

private Integer age;

}

接下来,创建一个新的配置类PropertyValueConfig,用来配置Spring的bean组件,我们在PropertyValueConfig类中将Person类的对象注册到IOC容器中,如下所示。

package io.mykit.spring.plugins.register.config;

import io.mykit.spring.plugins.register.bean.Person;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试属性赋值

*/

@Configuration

public class PropertyValueConfig {

@Bean

public Person person(){

return new Person();

}

}

我们再来创建一个测试类PropertyValueTest,在PropertyValueTest类中创建测试方法testPropertyValue01(),并在testPropertyValue01()方法中通过PropertyValueConfig类创建AnnotationConfigApplicationContext对象,打印出目前IOC容器中存在的bean名称,如下所示。

package io.mykit.spring.test;

import io.mykit.spring.plugins.register.config.PropertyValueConfig;

import org.junit.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试bean的生命周期

*/

public class PropertyValueTest {

@Test

public void testPropertyValue01(){

//创建IOC容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertyValueConfig.class);

String[] names = context.getBeanDefinitionNames();

Arrays.stream(names).forEach(System.out::println);

}

}

此时,我们运行PropertyValueTest类的testPropertyValue01()方法,输出的结果信息如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

org.springframework.context.event.internalEventListenerProcessor

org.springframework.context.event.internalEventListenerFactory

propertyValueConfig

person

从输出的结果信息中,可以看出,IOC容器中除了Spring框架注册的bean之外,还包含我们自己向IOC容器中注册的bean组件:propertyValueConfig和person。

接下来,我们改造下PropertyValueTest类的testPropertyValue01()方法,输出Person对象的信息,如下所示。

package io.mykit.spring.test;

import io.mykit.spring.plugins.register.bean.Person;

import io.mykit.spring.plugins.register.config.PropertyValueConfig;

import org.junit.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;

/**

  • @author binghe

  • @version 1.0.0

  • @description 测试bean的生命周期

*/

public class PropertyValueTest {

@Test

public void testPropertyValue01(){

//创建IOC容器

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertyValueConfig.class);

String[] names = context.getBeanDefinitionNames();

Arrays.stream(names).forEach(System.out::println);

System.out.println(“================================”);

Person person = (Person) context.getBean(“person”);

System.out.println(person);

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 29
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值