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

  • 相关阅读:
    【转】 java中Class对象详解和类名.class, class.forName(), getClass()区别
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    107. Binary Tree Level Order Traversal II
    109. Convert Sorted List to Binary Search Tree
    108. Convert Sorted Array to Binary Search Tree
    110. Balanced Binary Tree
    STL容器迭代器失效问题讨论
    113. Path Sum II
    112. Path Sum
  • 原文地址:https://www.cnblogs.com/nayitian/p/15413501.html
Copyright © 2011-2022 走看看