SpringBoot注入数据的方式

栏目: Java · 发布时间: 7年前

内容简介:通过@Value将外部的值动态注入到Bean中,使用的情况有:通过@Value将外部配置文件的值动态注入到Bean中。配置文件主要有两类:下面通过
SpringBoot注入数据的方式

1.不通过配置文件注入数据

通过@Value将外部的值动态注入到Bean中,使用的情况有:

  • 注入普通字符串
  • 注入操作系统属性
  • 注入表达式结果
  • 注入其他Bean属性:注入Student对象的属性name
  • 注入文件资源
  • 注入URL资源

辅助代码

package com.hannpang.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "st")//对student进行实例化操作
public class Student {
    @Value("悟空")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
复制代码

测试@Value的代码

package com.hannpang.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

@Component
public class SimpleObject {

    @Value("注入普通字符串")
    private String normal;

    //关于属性的KEY可以查看System类说明
    @Value("#{systemProperties['java.version']}")//-->使用了SpEL表达式
    private String systemPropertiesName; // 注入操作系统属性

    @Value("#{T(java.lang.Math).random()*80}")//获取随机数
    private double randomNumber; //注入表达式结果

    @Value("#{1+2}")
    private double sum; //注入表达式结果 1+2的求和

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

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

    @Value("#{st.name}")
    private String studentName;

    //省略getter和setter方法

    @Override
    public String toString() {
        return "SimpleObject{" +
                "normal='" + normal + '\'' +
                ", systemPropertiesName='" + systemPropertiesName + '\'' +
                ", randomNumber=" + randomNumber +
                ", sum=" + sum +
                ", resourceFile=" + resourceFile +
                ", testUrl=" + testUrl +
                ", studentName='" + studentName + '\'' +
                '}';
    }
}
复制代码

Spring的测试代码

package com.hannpang;

import com.hannpang.model.SimpleObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04BootApplicationTests {

    @Autowired
    private SimpleObject so;

    @Test
    public void contextLoads()  {
        System.out.println(so);
    }
}
复制代码
运行结果为:SimpleObject{normal='注入普通字符串', systemPropertiesName='1.8.0_172', randomNumber=56.631954541947266, sum=3.0, resourceFile=class path resource [os.yaml], testUrl=URL [http://www.baidu.com], studentName='悟空'}
复制代码

2.通过配置文件注入数据

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

  • application.properties、application.yaml application.properties在spring boot启动时默认加载此文件
  • 自定义属性文件 。自定义属性文件通过@PropertySource加载。@PropertySource可以同时加载多个文件,也可以加载单个文件。如果相同第一个属性文件和第二属性文件存在相同key,则最后一个属性文件里的key启作用。加载文件的路径也可以配置变量,如下文的${anotherfile.configinject},此值定义在第一个属性文件config.properties
  • 在application.properties中加入如下测试代码

    app.name=一步教育
    复制代码
  • 在resources下面新建第一个属性文件 config.properties 内容如下

    book.name=西游记
    anotherfile.configinject=system
    复制代码
  • 在resources下面新建第二个属性文件 config_system.properties 内容如下

    我的目的是想system的值使用第一个属性文件中定义的值

    book.name.author=吴承恩
    复制代码

下面通过 @Value(“${app.name}”) 语法将属性文件的值注入bean属性值,详细代码见:

package com.hannpang.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
@PropertySource(value = {"classpath:config.properties","classpath:config_${anotherfile.configinject}.properties"})
public class LoadPropsTest {

    @Value("${app.name}")
    private String appName; // 这里的值来自application.properties,spring boot启动时默认加载此文件

    @Value("${book.name}")
    private String bookName; // 注入第一个配置外部文件属性

    @Value("${book.name.author}")
    private String author; // 注入第二个配置外部文件属性

    @Autowired
    private Environment env;  // 注入环境变量对象,存储注入的属性值

    //省略getter和setter方法


    public void setAuthor(String author) {
        this.author = author;
    }


    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("bookName=").append(bookName).append("\r\n")
                .append("author=").append(author).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.author")).append("\r\n");
        return sb.toString();
    }

}
复制代码

测试代码

package com.hannpang;

import com.hannpang.model.SimpleObject;
import com.hannpang.test.LoadPropsTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04BootApplicationTests {

    @Autowired
    private LoadPropsTest lpt;

    @Test
    public void loadPropertiesTest()  {

        System.out.println(lpt);
    }
}
复制代码
运行结果为:
bookName=西游记
author=吴承恩
appName=一步教育
env=StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, MapPropertySource {name='Inlined Test Properties'}, MapPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}, ResourcePropertySource {name='class path resource [config_system.properties]'}, ResourcePropertySource {name='class path resource [config.properties]'}]}
env=吴承恩
复制代码

3. #{...}和${...} 的区别演示

A. ${…} 的用法

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

部分代码

// 如果属性文件没有app.name,则会报错
//  @Value("${app.name}")
//  private String name;

// 使用app.name设置值,如果不存在则使用默认值
@Value("${app.name:胖先森}")
private String name;
复制代码

B. #{...} 的用法

部分代码直接演示

// SpEL:调用字符串Hello World的concat方法
@Value("#{'Hello World'.concat('!')}")
private String helloWorld;

// SpEL: 调用字符串的getBytes方法,然后调用length属性
@Value("#{'Hello World'.bytes.length}")
private String helloWorldbytes;

复制代码

C. #{...}${...} 混合使用

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

// SpEL: 传入一个字符串,根据","切分后插入列表中, #{}和${}配置使用(注意单引号,注意不能反过来${}在外面,#{}在里面)
@Value("#{'${server.name}'.split(',')}")
private List<String> servers;
复制代码

在上文中在 #{}外面,${}在里面 可以执行成功,那么反过来是否可以呢 ${}在外面,#{}在里面 ,如代码

// SpEL: 注意不能反过来${}在外面,#{}在里面,这个会执行失败
@Value("${#{'HelloWorld'.concat('_')}}")
private List<String> servers2;
复制代码
答案是不能。
因为spring执行${}是时机要早于#{}。
在本例中,Spring会尝试从属性中查找#{‘HelloWorld’.concat(‘_’)},那么肯定找到,由上文已知如果找不到,然后报错。所以${}在外面,#{}在里面是非法操作
复制代码

D.用法总结

  • #{…} 用于执行SpEl表达式,并将内容赋值给属性
  • ${…} 主要用于加载外部属性文件中的值
  • #{…} 和${…} 可以混合使用,但是 必须#{}外面,${}在里面

4.@Value获取值和@ConfigurationProperties获取值比较

@ConfigurationProperties @Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

配置文件yml还是properties他们都能获取到值;

  • 如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;

  • 如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

关于数据校验的部分代码

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
   //lastName必须是邮箱格式
    @Email
    private String lastName;

复制代码

5. @ImportResource 引入配置文件

不推荐的使用方式

Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;

想让Spring的配置文件生效,加载进来;@ ImportResource 标注在一个配置类上

@ImportResource(locations = {"classpath:beans.xml"})
导入Spring的配置文件让其生效
复制代码

编写配置文件信息

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="helloService" class="com.hanpang.springboot.service.HelloService"></bean>
</beans>
复制代码

大概了解就好,我们基本上不使用这种方式

6. @Configuration 注解

SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式

1、配置类 @Configuration 作用于类上,相当于一个xml配置文件

2、使用 @Bean 给容器中添加组件,作用于方法上

/**
 * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
 *
 * 在配置文件中用<bean><bean/>标签添加组件
 * <bean id="helloService" class="com.hanpang.springboot.service.HelloService"></bean>
 */
@Configuration
public class MyAppConfig {

    //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
    @Bean
    public HelloService helloService02(){
        System.out.println("配置类@Bean给容器中添加组件了...");
        return new HelloService();
    }
}
复制代码

使用Bean注入太麻烦,我们更加喜欢使用扫描的方式

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
 
import com.wx.dao.IUserDao;
import com.wx.dao.UserDaoImpl;
 
//通过该注解来表明该类是一个Spring的配置,相当于一个传统的ApplicationContext.xml
@Configuration
//相当于配置文件里面的<context:component-scan/>标签,扫描这些包下面的类的注解
@ComponentScan(basePackages="com.hanpang.dao,com.hanpang.service")
public class SpringConfig {
	// 通过该注解来表明是一个Bean对象,相当于xml中的<bean>
	//bean的id值默认是方法名userDao
	/*
	@Bean
    public HelloService helloService02(){
        System.out.println("配置类@Bean给容器中添加组件了...");
        return new HelloService();
    }
	*/
}
复制代码

以上所述就是小编给大家介绍的《SpringBoot注入数据的方式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Shallows

The Shallows

Nicholas Carr / W. W. Norton & Company / 2011-6-6 / USD 15.95

"Is Google making us stupid?" When Nicholas Carr posed that question, in a celebrated Atlantic Monthly cover story, he tapped into a well of anxiety about how the Internet is changing us. He also crys......一起来看看 《The Shallows》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具