zoukankan      html  css  js  c++  java
  • Spring之@Value注解

    @Value 注解可以用来将外部的值动态注入到 Bean 中,在 @Value 注解中,可以使用 ${} 或 #{}。${} 与 #{} 的区别如下:

    (1)@Value("${}"):可以获取对应属性文件中定义的属性值。

    (2)@Value("#{}"):表示 SpEl 表达式通常用来获取 bean 的属性,或者调用 bean 的某个方法。

    @Value 注解的常用使用方式如下:

    一、注入普通字符串

    属性文件内容如下:

    str1=hello world

    Java代码如下:

    // 直接将字符串赋值给 str 属性
    @Value("hello world")
    private String str;
     
    // 从属性文件中获取值
    @Value("${str1}")
    private String str1; // 结果:hello world

    如果在属性文件中没有定义 str1 属性名,则 @Value 会抛出如下错误“java.lang.IllegalArgumentException: Could not resolve placeholder 'str1' in value "${str1}"”。我们可以在 str1 属性不存在时,指定默认值,即使没有定义 str2 也不会抛出错误,而是返回默认值。如下:

    @Value("${str2:defaultValue}")
    private String str2; // 结果:defaultValue

    二、注入操作系统属性

    可以利用 @Value 注入操作系统属性。这里我们不能使用“${}”去获取操作系统属性。如下:

    @Value("${systemProperties['os.name']}")
    private String osName;

    上面代码将抛出 java.lang.IllegalArgumentException: Could not resolve placeholder 'systemProperties['os.name']' in value "${systemProperties['os.name']}" 错误信息。你需要将 ${} 改为 #{},如下:

    @Value("#{systemProperties['os.name']}")
    private String osName; // 结果:Windows 10

    三、注入表达式结果

    在 @Value 中,允许我们使用表达式,然后自动计算表达式的结果。将结果复制给指定的变量。如下:

    // 生成一个随机数
    @Value("#{ T(java.lang.Math).random() * 1000.0 }")
    private double randomNumber;
     
    // 使用 System 类获取系统环境变量 PATH
    @Value("#{ T(java.lang.System).getenv('path') }")
    private String path;

    四、注入其他Bean属性

    在 @Value 注解中,也可以将其他 bean 的属性值注入到当前 bean。如下:

    // 其他Bean
    @Component
    public class OtherBean {
        @Value("OtherBean的NAME属性")
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
     
    // 用法
    @Component
    public class MyBean {
        @Value("#{otherBean.name}")
        private String fromAnotherBean;
        // ...
    }

    注意,其他 bean 使用 @Component 时,如果没有指定名称,则默认为类名首字母小写,如:otherBean 。当然我们也可以使用 @Component("myName") 形式,指定其他 bean 的名称,此时,访问则需要使用 @Value("#{myName.name}")。如下:

    // 其他bean,自定义名称为 myBeans
    @Component("myBeans")
    public class OtherBean2 {
        @Value("OtherBean的NAME属性")
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
     
    // 用法
    @Component
    public class MyBean {
        @Value("#{myBeans.name}")
        private String fromAnotherBean2;
        // ...
    }

    五、注入资源

    在 @Value 注解中,也可以用来注入资源(Resource),如:文件资源、URL网络资源等。如下:

    // 注入文件资源
    @Value("classpath:props/application.properties")
    private Resource fileResource;
     
    // 注入URL资源
    @Value("https://www.hxstrive.com")
    private Resource urlResource;

    完整代码如下:

    @Service
    public class ValueDemo5 {
     
        // 注入文件资源
        @Value("classpath:props/application.properties")
        private Resource fileResource;
     
        // 注入URL资源
        @Value("https://www.hxstrive.com")
        private Resource urlResource;
     
        public static void main(String[] args) throws Exception {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    "applicationContent-value.xml");
            ValueDemo5 demo = context.getBean(ValueDemo5.class);
     
            // 输出文件资源内容
            String fileContent = FileUtils.readFileToString(
                    demo.getFileResource().getFile(), "UTF-8");
            System.out.println(fileContent);
     
            // 输出URL资源内容
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            BufferedInputStream inputStream = new BufferedInputStream(
                    demo.getUrlResource().getInputStream());
            byte[] buffer = new byte[2048];
            int len;
            while((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            System.out.println(new String(outputStream.toByteArray(), "UTF-8"));
        }
     
        public Resource getFileResource() {
            return fileResource;
        }
     
        public void setFileResource(Resource fileResource) {
            this.fileResource = fileResource;
        }
     
        public Resource getUrlResource() {
            return urlResource;
        }
     
        public void setUrlResource(Resource urlResource) {
            this.urlResource = urlResource;
        }
    }

    六、@Value注入static属性

    一般@Value是使用在非静态方法上的,对于静态方法,以下做法是无效的:

    @Value("${myProp}")
    public static String myProp;

    如果要向静态属性注入值,可以使用set方法注入,如下:

    private static String str1;
     
    @Value("${str1}")
    public void setStr1(String str1) {
        System.out.println("setStr1 ===> " + str1);
        ValueDemo7.str1 = str1;
    }

    如果将 setStr1() 方法设置成 static,则 Spring 将抛出如下告警信息:

    13:26:34 WARN [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - Autowired annotation is not supported on static methods: public static void com.huangx.spring4.value.ValueDemo7.setStr1(java.lang.String) 

    七、引用外部属性文件

    通过 @Value 将外部配置文件的值动态注入到Bean中。配置文件主要有两类:

    application.properties

    在 spring boot 启动时默认加载此文件 application.properties,spring 则需要我们配置:

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <!-- 设置如果没有找到匹配的系统属性,是否搜索匹配的系统环境变量 -->
        <property name="searchSystemEnvironment" value="true" />
        <!-- 设置如何检查系统属性(SYSTEM_PROPERTIES_MODE_FALLBACK=1) -->
        <property name="systemPropertiesMode" value="1"/>
        <!-- 加载属性文件,指定属性文件地址,可以指定多个 -->
        <property name="locations">
            <list>
                <value>classpath:props/application.properties</value>
            </list>
        </property>
    </bean>

    自定义属性文件

    自定义属性文件通过 @PropertySource 加载,@PropertySource 可以同时加载多个文件,也可以加载单个文件。如果第一个属性文件和第二属性文件存在相同key,则最后一个属性文件里的key起作用(前面属性文件的key将被覆盖)。加载文件的路径也可以配置变量,如下面实例中 config.properties 属性文件的 ${env.model}(用来指定开发环境模式,如:dev-开发环境、prod-生产环境、test-测试环境)。属性文件定义如下:

    # config.properties 文件
    env.model=dev
     
    # config_dev.properties 文件
    name=
     
    # config_prod.properties 文件
    name=
     
    # config_test.properties 文件
    name=

    java 代码如下:

    // 引入多个属性配置文件
    @Component
    @PropertySource({
        "classpath:config.properties",
        "classpath:config_${env.model}.properties"
    })
    public class MyBean {
     
    }

    本文转载自:https://www.hxstrive.com/article/854.htm

  • 相关阅读:
    浏览器阻止window.open的解决方案
    汇总前端最最常用的JS代码片段
    检测是否是微信浏览器
    添加标签
    如何去掉textarea右下角的灰色角标?
    移动WEB前端开发资源整合
    图片文字水平居中(移动端)
    文本形式访客计数器
    如何处理加括号的四则混合运算表达式——基于二叉树的实现(Eclipse平台 Java版)
    深拷贝,浅拷贝
  • 原文地址:https://www.cnblogs.com/nayitian/p/15413501.html
Copyright © 2011-2022 走看看