mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Expand ConfigurationProperties doc
Closes gh-7620
This commit is contained in:
parent
cfad35ad21
commit
c8bdf74327
@ -815,34 +815,95 @@ will contain _one_ `MyPojo` entry (with name "`my another name`" and description
|
||||
[[boot-features-external-config-typesafe-configuration-properties]]
|
||||
=== Type-safe Configuration Properties
|
||||
Using the `@Value("${property}")` annotation to inject configuration properties can
|
||||
sometimes be cumbersome, especially if you are working with multiple properties or
|
||||
your data is hierarchical in nature. Spring Boot provides an alternative method
|
||||
of working with properties that allows strongly typed beans to govern and validate
|
||||
the configuration of your application. For example:
|
||||
sometimes be cumbersome, especially if you are working with multiple properties or your
|
||||
data is hierarchical in nature. Spring Boot provides an alternative method of working with
|
||||
properties that allows strongly typed beans to govern and validate the configuration of
|
||||
your application.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@ConfigurationProperties(prefix="connection")
|
||||
public class ConnectionProperties {
|
||||
package com.example;
|
||||
|
||||
private String username;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("foo")
|
||||
public class FooProperties {
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
private InetAddress remoteAddress;
|
||||
|
||||
// ... getters and setters
|
||||
private final Security security = new Security();
|
||||
|
||||
public boolean isEnabled() { ... }
|
||||
|
||||
public void setEnabled(boolean enabled) { ... }
|
||||
|
||||
public InetAddress getRemoteAddress() { ... }
|
||||
|
||||
public void setRemoteAddress(InetAddress remoteAddress) { ... }
|
||||
|
||||
public Security getSecurity() { ... }
|
||||
|
||||
public static class Security {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
|
||||
|
||||
public String getUsername() { ... }
|
||||
|
||||
public void setUsername(String username) { ... }
|
||||
|
||||
public String getPassword() { ... }
|
||||
|
||||
public void setPassword(String password) { ... }
|
||||
|
||||
public List<String> getRoles() { ... }
|
||||
|
||||
public void setRoles(List<String> roles) { ... }
|
||||
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: The getters and setters are advisable, since binding is via standard Java Beans
|
||||
property descriptors, just like in Spring MVC. They are mandatory for immutable types or
|
||||
those that are directly coercible from `String`. As long as they are initialized, maps,
|
||||
collections, and arrays need a getter but not necessarily a setter since they can be
|
||||
mutated by the binder. If there is a setter, Maps, collections, and arrays can be created.
|
||||
Maps and collections can be expanded with only a getter, whereas arrays require a setter.
|
||||
Nested POJO properties can also be created (so a setter is not mandatory) if they have a
|
||||
default constructor, or a constructor accepting a single value that can be coerced from
|
||||
String. Some people use Project Lombok to add getters and setters automatically.
|
||||
The POJO above defines the following properties:
|
||||
|
||||
* `foo.enabled`, `false` by default
|
||||
* `foo.remote-address`, with a type that can be coerced from `String`
|
||||
* `foo.security.username`, with a nested "security" whose name is determined by the name
|
||||
of the property. In particular the return type is not used at all there and could have
|
||||
been `SecurityProperties`
|
||||
* `foo.security.password`
|
||||
* `foo.security.roles`, with a collection of `String`
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Getters and setters are usually mandatory, since binding is via standard Java Beans
|
||||
property descriptors, just like in Spring MVC. There are cases where a setter may be
|
||||
omitted:
|
||||
|
||||
* Maps, as long as they are initialized, need a getter but not necessarily a setter since
|
||||
they can be mutated by the binder.
|
||||
* Collections and arrays can be either accessed via an index (typically with YAML) or
|
||||
using a single comma-separated value (properties). In the latter case, a setter is
|
||||
mandatory. We recommend to always add a setter for such types. If you initialize a
|
||||
collection, make sure it is not immutable (as in the example above)
|
||||
* If nested POJO properties are initialized (like the `Security` field in the example
|
||||
above), a setter is not required. If you want the binder to create the instance on-the-fly
|
||||
using its default constructor, you will need a setter.
|
||||
|
||||
Some people use Project Lombok to add getters and setters automatically. Make sure that
|
||||
Lombok doesn't generate any particular constructor for such type as it will be used
|
||||
automatically by the container to instantiate the object.
|
||||
====
|
||||
|
||||
TIP: See also the <<boot-features-external-config-vs-value,differences between `@Value`
|
||||
and `@ConfigurationProperties`>>.
|
||||
@ -853,7 +914,7 @@ You also need to list the properties classes to register in the
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ConnectionProperties.class)
|
||||
@EnableConfigurationProperties(FooProperties.class)
|
||||
public class MyConfiguration {
|
||||
}
|
||||
----
|
||||
@ -862,29 +923,28 @@ You also need to list the properties classes to register in the
|
||||
====
|
||||
When `@ConfigurationProperties` bean is registered that way, the bean will have a
|
||||
conventional name: `<prefix>-<fqn>`, where `<prefix>` is the environment key prefix
|
||||
specified in the `@ConfigurationProperties` annotation and <fqn> the fully qualified
|
||||
specified in the `@ConfigurationProperties` annotation and `<fqn>` the fully qualified
|
||||
name of the bean. If the annotation does not provide any prefix, only the fully qualified
|
||||
name of the bean is used.
|
||||
|
||||
The bean name in the example above will be `connection-com.example.ConnectionProperties`,
|
||||
assuming that `ConnectionProperties` sits in the `com.example` package.
|
||||
The bean name in the example above will be `foo-com.example.FooProperties`.
|
||||
====
|
||||
|
||||
Even if the configuration above will create a regular bean for `ConnectionProperties`, we
|
||||
Even if the configuration above will create a regular bean for `FooProperties`, we
|
||||
recommend that `@ConfigurationProperties` only deal with the environment and in particular
|
||||
does not inject other beans from the context. Having said that, The
|
||||
`@EnableConfigurationProperties` annotation is _also_ automatically applied to your project
|
||||
so that any _existing_ bean annotated with `@ConfigurationProperties` will be configured
|
||||
from the `Environment` properties. You could shortcut `MyConfiguration` above by making
|
||||
sure `ConnectionProperties` is a already a bean:
|
||||
from the `Environment`. You could shortcut `MyConfiguration` above by making sure
|
||||
`FooProperties` is a already a bean:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Component
|
||||
@ConfigurationProperties(prefix="connection")
|
||||
public class ConnectionProperties {
|
||||
@Component
|
||||
@ConfigurationProperties(prefix="foo")
|
||||
public class FooProperties {
|
||||
|
||||
// ... getters and setters
|
||||
// ... see above
|
||||
|
||||
}
|
||||
----
|
||||
@ -896,9 +956,13 @@ This style of configuration works particularly well with the
|
||||
----
|
||||
# application.yml
|
||||
|
||||
connection:
|
||||
username: admin
|
||||
remoteAddress: 192.168.1.1
|
||||
foo:
|
||||
remote-address: 192.168.1.1
|
||||
security:
|
||||
username: foo
|
||||
roles:
|
||||
- USER
|
||||
- ADMIN
|
||||
|
||||
# additional configuration as required
|
||||
----
|
||||
@ -911,26 +975,27 @@ as any other bean.
|
||||
@Service
|
||||
public class MyService {
|
||||
|
||||
private final ConnectionProperties connection;
|
||||
private final FooProperties properties;
|
||||
|
||||
@Autowired
|
||||
public MyService(ConnectionProperties connection) {
|
||||
this.connection = connection;
|
||||
public MyService(FooProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
//...
|
||||
|
||||
@PostConstruct
|
||||
public void openConnection() {
|
||||
Server server = new Server();
|
||||
this.connection.configure(server);
|
||||
Server server = new Server(this.properties.getRemoteAddress());
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
TIP: Using `@ConfigurationProperties` also allows you to generate meta-data files that can
|
||||
be used by IDEs. See the <<configuration-metadata>> appendix for details.
|
||||
be used by IDEs to offer auto-completion for your own keys, see the
|
||||
<<configuration-metadata>> appendix for details.
|
||||
|
||||
|
||||
|
||||
@ -945,15 +1010,15 @@ its bean registration:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@ConfigurationProperties(prefix = "foo")
|
||||
@ConfigurationProperties(prefix = "bar")
|
||||
@Bean
|
||||
public FooComponent fooComponent() {
|
||||
public BarComponent barComponent() {
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
Any property defined with the `foo` prefix will be mapped onto that `FooComponent` bean
|
||||
in a similar manner as the `ConnectionProperties` example above.
|
||||
Any property defined with the `bar` prefix will be mapped onto that `BarComponent` bean
|
||||
in a similar manner as the `FooProperties` example above.
|
||||
|
||||
|
||||
|
||||
@ -1031,8 +1096,8 @@ annotations to your `@ConfigurationProperties` class:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@ConfigurationProperties(prefix="connection")
|
||||
public class ConnectionProperties {
|
||||
@ConfigurationProperties(prefix="foo")
|
||||
public class FooProperties {
|
||||
|
||||
@NotNull
|
||||
private InetAddress remoteAddress;
|
||||
@ -1044,23 +1109,25 @@ annotations to your `@ConfigurationProperties` class:
|
||||
|
||||
In order to validate values of nested properties, you must annotate the associated field
|
||||
as `@Valid` to trigger its validation. For example, building upon the above
|
||||
`ConnectionProperties` example:
|
||||
`FooProperties` example:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@ConfigurationProperties(prefix="connection")
|
||||
public class ConnectionProperties {
|
||||
public class FooProperties {
|
||||
|
||||
@NotNull
|
||||
private InetAddress remoteAddress;
|
||||
|
||||
@Valid
|
||||
private RemoteAddress remoteAddress;
|
||||
private final Security security = new Security();
|
||||
|
||||
// ... getters and setters
|
||||
|
||||
public static class RemoteAddress {
|
||||
public static class Security {
|
||||
|
||||
@NotEmpty
|
||||
public String hostname;
|
||||
public String username;
|
||||
|
||||
// ... getters and setters
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user