好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

详解SpringBoot注入数据的方式

关于注入数据说明

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

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

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

辅助代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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的代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

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的测试代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

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中加入如下测试代码

?

1

app.name=一步教育

在resources下面新建第一个属性文件 config.properties 内容如下

?

1

2

book.name=西游记

anotherfile.configinject=system

在resources下面新建第二个属性文件 config_system.properties 内容如下

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

?

1

book.name.author=吴承恩

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

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();

   }

 

}

测试代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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:胖先森}")

部分代码

?

1

2

3

4

5

6

7

// 如果属性文件没有app.name,则会报错

// @value("${app.name}")

// private string name;

 

// 使用app.name设置值,如果不存在则使用默认值

@value ( "${app.name:胖先森}" )

private string name;

b. #{...} 的用法

部分代码直接演示

?

1

2

3

4

5

6

7

// 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(‘,')}。

?

1

2

3

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

@value ( "#{'${server.name}'.split(',')}" )

private list<string> servers;

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

?

1

2

3

// 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;

关于数据校验的部分代码

?

1

2

3

4

5

6

7

@component

@configurationproperties (prefix = "person" )

@validated

public class person {

   //lastname必须是邮箱格式

   @email

   private string lastname;

5. @importresource引入配置文件

不推荐的使用方式

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

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

?

1

2

@importresource (locations = { "classpath:beans.xml" })

导入spring的配置文件让其生效

编写配置文件信息

?

1

2

3

4

5

6

<?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 给容器中添加组件,作用于方法上

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/**

  * @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注入太麻烦,我们更加喜欢使用扫描的方式

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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();

   }

   */

}

附录

随机数

?

1

2

${random.value}、${random. int }、${random. long }

${random. int ( 10 )}、${random. int [ 1024 , 65536 ]}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

原文链接:https://segmentfault.com/a/1190000017485165

查看更多关于详解SpringBoot注入数据的方式的详细内容...

  阅读:17次