文档章节

《Spring5学习》 03 运行时值注入

 何如泛轻舟
发布于 2018/08/14 13:35
字数 1667
阅读 24
收藏 3

Spring的运行时值注入是为了在一些应用场景避免将属性值硬编码在配置类中而提供的解决方案,Spring目前提供了几种方式实现运行时值注入,下面我们分别来讲下

 

1 - Spring中的Environment

    在Spring中,注入外部属性值的最简单方式就是声明一个外部属性源并通过Spring的Environment检索该属性。示例代码如下:

package com.example.demo.config;

import com.example.demo.model.UserBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;


@Configuration
@PropertySource("classpath:app.properties")
public class ValueAutoInputConfig {
    @Autowired
    private Environment env;

    @Bean
    public UserBean userBean(){
        return new UserBean(env.getProperty("user.userBean.name"), env.getProperty("user.userBean.password"));
    }

}

对应的属性配置文件app.properties

user.userBean.name=yanqingzhang
user.userBean.password=123456

    Environment属性相关方法如下:

    //获取指定key对应的属性值
    String getProperty(String key);
    //获取指定key对应的属性值,当获取的属性值为空时返回默认值defaultValue
    String getProperty(String key, String defaultValue);

    //获取指定key对应的属性值,指定返回的属性值类型为type指定的类型
    <T> T getProperty(String key, Class<T> type);
    //获取指定key对应的属性值,指定返回的属性值类型为type指定的类型,当获取的属性值为null时返回默认值defaultValue
    <T> T getProperty(String key, Class<T> type, T defaultValue);

    //获取key对应的属性值,默认返回的String对象,如果未指定属性key则抛出IllegalStateException异常
    String getRequiredProperty(String key) throws IllegalStateException;

    //获取key对应的属性值,并基于type指定返回的属性值类型,如果未指定属性key则抛出IllegalStateException异常
    <T> T getRequiredProperty(String var1, Class<T> type) throws IllegalStateException;

    //判断指定属性key是否存在
    boolean containsProperty(String key);

2 - 使用属性占位符在运行时注入值

    Spring支持将属性定义到外部的属性文件中,然后在Spring Bean需要的使用的时候使用占位符将属性值注入进来,占位符的使用形式为”${}“,我们下面列举在XML和@Value注解中使用属性占位符

    在使用占位符之前我们首先必须配置一个PropertySourcesPlaceholderConfigurer类bean,我们可以采用两种方式配置该Spring Bean一种是在XML配置文件中添加命令空间<context:property-placeholder />,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd
">
    <context:property-placeholder />
</beans>

 

另一种则是使用@Bean注解在Java配置类中声明,代码如下:

@Configuration
@PropertySource("classpath:app.properties")
@ComponentScan(basePackageClasses = {UserBean.class})
public class ValueAutoInputConfig {
    @Autowired
    private Environment env;

    @Bean
    public PropertySourcesPlaceholderConfigurer placeholderConfigurer(){
        return new PropertySourcesPlaceholderConfigurer();
    }

}

 

1)在XML配置文件中使用占位符

    <bean id="userBean" class="com.jiayun.spring.learn.model.UserBean">
        <property name="name" value="${user.userBean.name}" />
        <property name="password" value="${user.userBean.password}" />
    </bean>

2)在@Value注解中使用属性占位符

@Component
public class UserBean {
    @Value("${user.userBean.name}")
    private String name;

    @Value("${user.userBean.password}")
    private String password;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

    解析外部属性能够将值的处理推迟到运行时,但是它只能根据属性名称获取来自Spring Environment和外部属性源的属性配置,下面讲述的Spring表达式语言(SpEL)提供更加强大的功能

3 - 使用Spring表达式语言装配

    Spring表达式语言(SpEL)能够以一种非常简介且强大的方式将运行时外部值装配到到bean属性和构造器参数中,它主要有以下几种使用方式:

1)表示字面值

@Component
public class UserBean {
    @Value("#{'yanqingzhang'}")
    private String name;

    @Value("#{123456}")
    private String password;
    ......
}

2)引用Bean、属性和方法

引用Bean

@Service
public class UserBeanQuery {
    @Value("#{userBean}")
    private UserBean userBean;

    ......
}

引用Bean属性

@Service
public class UserBeanQuery {

    @Value("#{userBean.name}")
    private String userName;

    public String getUserName(){
        System.out.println(userName);
        return userName;
    }
}

引用方法

@Service
public class UserBeanQuery {

    @Value("#{userBean.getName().toUpperCase()}")
    private String userName;

    public String getUserName(){
        System.out.println(userName);
        return userName;
    }
}

为了避免userBean.getName()返回的String对象为null还可以这样写防止NullPointException,采用以下方式写执行到getName方法返回null对象时表达式直接返回null不再执行后面的转大写方法toUpperCase

@Service
public class UserBeanQuery {

    @Value("#{userBean.getName()?.toUpperCase()}")
    private String userName;

    public String getUserName(){
        System.out.println(userName);
        return userName;
    }
}

3)在表达式中使用类型

    如果需要在表达式中访问类作用域的方法和常量必须得依赖T()这个关键的运算符,例如要在SpEL表达式中使用Java的Math类可以写成T(java.io.Math),T()关键运算符的作用是可以让我们可以访问目标类内部的静态成员变量和静态成员方法,当然我们也可以将T()运算符结果的Class对象和普通Bean一样装配到Bean属性中

@Service
public class UserBeanQuery {
    @Value("#{T(java.lang.Math).random()*20}")
    private int age;
}

4)SpEL运算符

    SpEL提供了许多运算符,几乎支持所有的算术、比较、逻辑、条件、正则运算,以下运算符都可以应用于SpEL表达式

运算符类型 运算符
算术运算 +、-、*、/、%、^
比较运算符 <、>、==、<=、>=、lt、gt、eq、le、ge
逻辑运算符 and、or、not、|
条件运算符 三元运算( exp ? value1 : value2)、Evis运算符(exp ?: value)
正则表达式 matches

这里讲解下Evis运算符的使用,例如这样一个Evis运算符表达式exp ?: value 假如exp是null那么表达式的计算结果就是value。如下给出在@Value注解上使用示例:

@Service
public class UserBeanQuery {
    @Value("#{userBean.getName() ?: 'defaultName'}")
    private String userName;

    public String getUserName(){
        System.out.println(userName);
        return userName;
    }
}

 

5 )使用正则表达式

@Service
public class UserBeanQuery {

    @Value("#{userBean.email matches '[a-zA-Z0-9_]+@[a-zA-Z_]+\\.com'}")
    private boolean isTrueEmail;


    public Boolean isTrueEmail(){
        return isTrueEmail;
    }
}

注意UserBean的类中必须实现email属性的get/set方法

 

6 - 计算集合

    SpEL支持基于索引下标获取集合和数组的元素,在此基础上还提供了查询运算符 ” .?[] “,他会用来对集合或数组进行过滤得到集合或者数组的一个子集过滤条件放在中括号[]之内,SpEL还支持其他两个运算符” .^[ ] “和” .$[ ]“分别用于在集合中查询匹配中括号内过滤条件的第一项和最后一项元素,最后SpEL表达式还支持投影运算符” .![] “他会从集合中每个元素中选择指定属性放到另外一个集合上,这个属性在中括号[]中指定,以下是在@Value注解中的使用示例

© 著作权归作者所有

粉丝 13
博文 64
码字总数 107681
作品 0
杭州
后端工程师
私信 提问
《Spring5学习》 01 装配Bean之自动化装配

Spring的自动化装配就便利性方面远远优于其他装配方法,这也是业界目前主要采用的Bean装配机制。Spring基于组建扫描和自动装配实现自动化装配,能将用户的显示配置降到最低。以下通过一段代码...

老韭菜
2018/08/05
0
0
《Spring5学习》04 - 面向切面编程

一、Spring面向切面编程的基本概念 面向切面编程(即AOP):把项目中需要再多处使用的功能比如日志、安全和事务等集中到一个类中处理,而不用在每个需要用到该功能的地方显式调用。 横切关注...

老韭菜
2018/08/19
0
0
Web 安全渗透学习路线----1Web安全相关概念

SQL: sql注入百度百科http://baike.baidu.com/view/3896.htm(包含注入方法) sql注入原理讲解http://blog.csdn.net/stilling2006/article/details/8526458 sql注入攻击过程http://blog.jobbo......

NNigel
2015/11/12
0
0
go 1发布了,之前写的代码不能运行了

刚刚发布go 1 ,迫不及待的进行更新,可问题出来了: 1、8g的命令不能用了 我的平台是windows,用notepad++配置了开发环境(http://www.cnblogs.com/MikeZhang/archive/2012/02/10/nppRunGo....

长平狐
2012/06/08
427
0
渗透攻防Web篇-SQL注入攻击初级

不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动。在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞之一,...

白帽生活
2016/12/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

海康威视Web3.0控件个人开发经验及问题总结(转)

最近在给公司平台写视频监控的页面需求,于是接触到了海康威视的视频控件,网上查阅一番资料后,发现有很多大佬们给出了简易的海康视频控件的上手方法,但是发现仍然有很多地方没有总结到,于...

west_coast
6分钟前
0
0
spring boot入门,看这篇文章就够了

一、SpringBoot入门 1、基本介绍 简化Spring应用开发的一个框架、整个Spring技术栈的一个大整合; J2EE开发的一站式解决方案; 优点: 快速创建独立运行的Spring项目以及与主流框架集成; 使...

李红欧巴
11分钟前
1
0
solidity智能合约implicit conversion异常

问题场景 在使用^0.5.10版本的solidity时,如果使用this关键字会出现以下问题。 代码: require(tokenContract.balanceOf(this) >= _numberOfTokens);(issue is here) 错误信息: TypeErro...

程序新视界
13分钟前
0
0
Null value appeared in non-nullable field java.lang.NullPointerException

报错 Null value appeared in non-nullable fieldjava.lang.NullPointerException: Null value appeared in non-nullable field: top level row objectIf the schema is inferred from a......

张欢19933
19分钟前
0
0
【百度飞浆AI Studio】2、感性快速体验深度学习的线性归回预测房价

百度学习原文地址: https://www.paddlepaddle.org.cn/documentation/docs/zh/1.5/beginners_guide/basics/fit_a_line/README.cn.html import paddleimport paddle.fluid as fluidimport n......

-个俗人
19分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部