Skip to content

Commit 3b99491

Browse files
committed
📝 spring
1 parent a929a22 commit 3b99491

12 files changed

+7846
-0
lines changed

docs/framework/Spring/@Value.md

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# Spring @Value快速指南,这50种注入形式肯定有用到的时候
2+
3+
Spring boot 允许我们把配置信息外部化。由此,我们就可以在不同的环境中使用同一套程序代码。可以使用属性文件,yaml文件,环境变量,命令行参数来实现配置信息的外部化。
4+
5+
可以使用 `@Value` 注解来将属性值直接注入到bean里边。也可以使用 `@ConfigurationProperties` 注解将属性值注入到结构化的对象里边。
6+
7+
8+
9+
这篇我们主要整理下 @Value 的各种用法。
10+
11+
`@Value` 通常用于注入外部属性,Spring Boot 会自动加载的配置文件 `application.properties` 中的属性;
12+
13+
如果是自定义的其他命名配置文件,需要先通过 `@PropertySource` 加载自定义属性文件。
14+
15+
16+
17+
## 使用
18+
19+
application.properties
20+
21+
```properties
22+
catalog.name=MovieCatalog
23+
value.from.file=Value got from the file
24+
priority=high
25+
listOfValues=A,B,C
26+
ip=192.168.0.1
27+
port=8080
28+
url=www.baidu.com
29+
valuesMap={key1: '1', key2: '2', key3: '3'}
30+
```
31+
32+
## 用法实例
33+
34+
```java
35+
/**
36+
* 注入普通字符串,相当于直接给属性默认值
37+
*/
38+
@Value("normal")
39+
private String normal;
40+
41+
/**
42+
* 默认获取位于application.properties中配置的属性,也可以注入基本数据类型
43+
* 如果系统属性中有该值,也会获取到
44+
*/
45+
@Value("${value.from.file}")
46+
private String valueFromFile;
47+
48+
/**
49+
* 注入数组(自动根据","分割)
50+
*/
51+
@Value("${listOfValues}")
52+
private String[] valuesArray;
53+
54+
/**
55+
* 注入列表形式(自动根据","分割)
56+
*/
57+
@Value("${listOfValues}")
58+
private List<String> valuesList;
59+
60+
/**
61+
* 注入文件资源
62+
*/
63+
@Value("classpath:application.properties")
64+
private Resource resourceFile;
65+
66+
/**
67+
* 注入URL资源,不可以通过配置文件注入,会:
68+
* Failed to convert value of type 'java.lang.String' to required type 'java.net.URL';
69+
*/
70+
@Value("http://www.google.com")
71+
private URL testUrl;
72+
```
73+
74+
75+
76+
## SpEL 表达式
77+
78+
SpEL 表达式是很强大的,可以获取系统属性、调用静态方法、计算、注入bean、调用bean的方法等等
79+
80+
```java
81+
/**
82+
* 注入List,可以根据设定分隔符截取
83+
*/
84+
@Value("#{'${listOfValues}'.split(',')}")
85+
private List<String> values;
86+
87+
/**
88+
* 注入操作系统属性,如果有自定义的系统属性,也可以通过该方式注入
89+
*/
90+
@Value("#{systemProperties['os.name']}")
91+
private String systemPropertiesName;
92+
93+
/**
94+
* 我们还可以使用@Value注释注入所有当前系统属性
95+
*/
96+
@Value("#{systemProperties}")
97+
private Map<String, String> systemPropertiesMap;
98+
99+
/**
100+
* 注入表达式结果
101+
*/
102+
@Value("#{ T(java.lang.Math).random() * 100.0 }")
103+
private double randomNumber;
104+
105+
/**
106+
* 注入其他Bean属性:注入movieRecommender对象的属性catalog,对象属性要有get set方法
107+
*/
108+
@Value("#{movieRecommender.catalog}")
109+
private String fromAnotherBean;
110+
```
111+
112+
113+
114+
## 注入 Map
115+
116+
```java
117+
/**
118+
* 注入Map, 需要注意的是map中的value 必须用单引号引起来
119+
*/
120+
@Value("#{${valuesMap}}")
121+
private Map<String, Integer> valuesMap;
122+
123+
/**
124+
* 获取 map 中的某个key值
125+
*/
126+
@Value("#{${valuesMap}.key1}")
127+
private Integer valuesMapKey1;
128+
129+
/**
130+
* 如果我们不确定Map是否包含某个键,则应选择一个更安全的表达式,该表达式不会引发异常,但在找不到该键时将其值设置为null:
131+
*/
132+
@Value("#{${valuesMap}['key4']}")
133+
private Integer unknownMapKey;
134+
135+
/**
136+
* 我们还可以为可能不存在的属性或键设置默认值:
137+
*/
138+
@Value("#{${unknownMap : {key1: '1', key2: '2'}}}")
139+
private Map<String, Integer> unknownMap;
140+
141+
@Value("#{${valuesMap}['unknownKey'] ?: 5}")
142+
private Integer unknownMapKeyWithDefaultValue;
143+
144+
/**
145+
* map 也可以在注入前过滤。假设我们只需要获取值大于一的键值对
146+
*/
147+
@Value("#{${valuesMap}.?[value>'1']}")
148+
private Map<String, Integer> valuesMapFiltered;
149+
```
150+
151+
152+
153+
## 指定默认值
154+
155+
```java
156+
/**
157+
* 如果属性中未配置ip,则使用默认值
158+
*/
159+
@Value("${ip:127.0.0.1}")
160+
private String ip;
161+
162+
/**
163+
* 如果系统属性中未获取到port的值,则使用9090
164+
* 其中${}中直接使用“:”对未定义或为空的值进行默认值设置,
165+
* 而#{}则需要使用“?:”对未设置的属性进行默认值设置
166+
*/
167+
@Value("#{systemProperties['port']?:'9090'}")
168+
private String port;
169+
170+
@Value("#{systemProperties['unknown'] ?: 'some default'}")
171+
private String spelSomeDefault;
172+
```
173+
174+
175+
176+
## 在构造器注入中使用*@Value*
177+
178+
@Value不仅仅限于字段注入,我们也可以将其与构造函数注入一起使用
179+
180+
```java
181+
@Component
182+
@PropertySource("classpath:values.properties")
183+
public class PriorityProvider {
184+
185+
private String priority;
186+
187+
@Autowired
188+
public PriorityProvider(@Value("${priority:normal}") String priority) {
189+
this.priority = priority;
190+
}
191+
192+
// standard getter
193+
194+
195+
public String getPriority() {
196+
return priority;
197+
}
198+
}
199+
```
200+
201+
202+
203+
## 在Setter注入中使用@Value
204+
205+
```java
206+
@Component
207+
@PropertySource("classpath:values.properties")
208+
public class CollectionProvider {
209+
210+
private List<String> values = new ArrayList<>();
211+
212+
@Autowired
213+
public void setValues(@Value("#{'${listOfValues}'.split(',')}") List<String> values){
214+
this.values.addAll(values);
215+
}
216+
217+
// standard getter
218+
}
219+
```
220+
221+
222+
223+
## 原理
224+
225+
226+
227+
228+
229+
230+
231+
参考:
232+
233+
https://www.baeldung.com/spring-value-annotation

docs/framework/Spring/My-Spring.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# 手写 Spring
2+
3+
![image-20201106173130849](https://cdn.jsdelivr.net/gh/Jstarfish/picBed/img/20201106173132.png)
4+
配置阶段:主要是完成application.xml配置和Annotation配置。
5+
6+
初始化阶段:主要是加载并解析配置信息,然后,初始化IOC容器,完成容器的DI操作,已经完成HandlerMapping的初始化。
7+
8+
运行阶段:主要是完成Spring容器启动以后,完成用户请求的内部调度,并返回响应结果。
9+
=======
10+
11+
12+
```undefined
13+
⑴ 用户发送请求至前端控制器DispatcherServlet
14+
15+
⑵ DispatcherServlet收到请求调用HandlerMapping处理器映射器。
16+
17+
⑶ 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
18+
19+
⑷ DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
20+
21+
⑸ 执行处理器(Controller,也叫后端控制器)。
22+
23+
⑹ Controller执行完成返回ModelAndView
24+
25+
⑺ HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
26+
27+
⑻ DispatcherServlet将ModelAndView传给ViewReslover视图解析器
28+
29+
⑼ ViewReslover解析后返回具体View
30+
31+
⑽ DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
32+
33+
⑾ DispatcherServlet响应用户。
34+
```

0 commit comments

Comments
 (0)