anchor.diff:  
   
   
  +[[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 lets strongly typed beans govern and validate the configuration of
  +your application, as shown in the following example:
  +
  +[source,java,indent=0]
  +----
  +	package com.example;
  +
  +	import java.net.InetAddress;
  +	import java.util.ArrayList;
  +	import java.util.Collections;
  +	import java.util.List;
  +
  +	import org.springframework.boot.context.properties.ConfigurationProperties;
  +
  +	@ConfigurationProperties("acme")
  +	public class AcmeProperties {
  +
  +		private boolean enabled;
  +
  +		private InetAddress remoteAddress;
  +
  +		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) { ... }
  +
  +		}
  +	}
  +----
  +
  +The preceding POJO defines the following properties:
  +
  +* `acme.enabled`, with a value of `false` by default.
  +* `acme.remote-address`, with a type that can be coerced from `String`.
  +* `acme.security.username`, with a nested "security" object 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`.
  +* `acme.security.password`.
  +* `acme.security.roles`, with a collection of `String`.
  +
  +[NOTE]
  +====
  +Getters and setters are usually mandatory, since binding is through standard Java Beans
  +property descriptors, just like in Spring MVC. A setter may be omitted in the following
  +cases:
  +
  +* 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 accessed either through an index (typically with YAML) or
  +by 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 preceding example).
  +* If nested POJO properties are initialized (like the `Security` field in the preceding
  +example), a setter is not required. If you want the binder to create the instance on the
  +fly by using its default constructor, you need a setter.
  +
  +Some people use Project Lombok to add getters and setters automatically. Make sure that
  +Lombok does not generate any particular constructor for such a type, as it is used
  +automatically by the container to instantiate the object.
  +
  +Finally, only standard Java Bean properties are considered and binding on static
  +properties are not supported.
  +====
  +
  +TIP: See also the <<boot-features-external-config-vs-value,differences between `@Value`
  +and `@ConfigurationProperties`>>.
  +
  +You also need to list the properties classes to register in the
  +`@EnableConfigurationProperties` annotation, as shown in the following example:
  +
  +[source,java,indent=0]
  +----
  +	@Configuration
  +	@EnableConfigurationProperties(AcmeProperties.class)
  +	public class MyConfiguration {
  +	}
  +----
  +
  +[NOTE]
  +====
  +When the `@ConfigurationProperties` bean is registered that way, the bean has a
  +conventional name: `<prefix>-<fqn>`, where `<prefix>` is the environment key prefix
  +specified in the `@ConfigurationProperties` annotation and `<fqn>` is 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 is `acme-com.example.AcmeProperties`.
  +====
  +
  +Even if the preceding configuration creates a regular bean for `AcmeProperties`, 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` is
  +configured from the `Environment`. You could shortcut `MyConfiguration` by making sure
  +`AcmeProperties` is already a bean, as shown in the following example:
  +
  +[source,java,indent=0]
  +----
  +	@Component
  +	@ConfigurationProperties(prefix="acme")
  +	public class AcmeProperties {
  +
  +		// ... see the preceding example
  +
  +	}
  +----
  +
  +This style of configuration works particularly well with the `SpringApplication` external
  +YAML configuration, as shown in the following example:
  +
  +[source,yaml,indent=0]
  +----
  +	# application.yml
  +
  +	acme:
  +		remote-address: 192.168.1.1
  +		security:
  +			username: admin
  +			roles:
  +			  - USER
  +			  - ADMIN
  +
  +	# additional configuration as required
  +----
  +
  +To work with `@ConfigurationProperties` beans, you can inject them in the same way
  +as any other bean, as shown in the following example:
  +
  +[source,java,indent=0]
  +----
  +	@Service
  +	public class MyService {
  +
  +		private final AcmeProperties properties;
  +
  +		@Autowired
  +		public MyService(AcmeProperties properties) {
  +		    this.properties = properties;
  +		}
  +
  +	 	//...
  +
  +		@PostConstruct
  +		public void openConnection() {
  +			Server server = new Server(this.properties.getRemoteAddress());
  +			// ...
  +		}
  +
  +	}
  +----
  +
  +TIP: Using `@ConfigurationProperties` also lets you generate metadata files that can be
  +used by IDEs to offer auto-completion for your own keys. See the
  +<<configuration-metadata>> appendix for details.
  +
  +
  +
  +[[boot-features-external-config-3rd-party-configuration]]
  +==== Third-party Configuration
  +As well as using `@ConfigurationProperties` to annotate a class, you can also use it on
  +public `@Bean` methods. Doing so can be particularly useful when you want to bind
  +properties to third-party components that are outside of your control.
  +
  +To configure a bean from the `Environment` properties, add `@ConfigurationProperties` to
  +its bean registration, as shown in the following example:
  +
  +[source,java,indent=0]
  +----
  +	@ConfigurationProperties(prefix = "another")
  +	@Bean
  +	public AnotherComponent anotherComponent() {
  +		...
  +	}
  +----
  +
  +Any property defined with the `another` prefix is mapped onto that `AnotherComponent` bean
  +in manner similar to the preceding `AcmeProperties` example.
  +
  +
  +
  +[[boot-features-external-config-relaxed-binding]]
  +==== Relaxed Binding
  +Spring Boot uses some relaxed rules for binding `Environment` properties to
  +`@ConfigurationProperties` beans, so there does not need to be an exact match between the
  +`Environment` property name and the bean property name.  Common examples where this is
  +useful include dash-separated environment properties (for example, `context-path` binds
  +to `contextPath`), and capitalized environment properties (for example, `PORT` binds to
  +`port`).
  +
  +For example, consider the following `@ConfigurationProperties` class:
  +
  +[source,java,indent=0]
  +----
  +	@ConfigurationProperties(prefix="acme.my-project.person")
  +	public class OwnerProperties {
  +
  +		private String firstName;
  +
  +		public String getFirstName() {
  +			return this.firstName;
  +		}
  +
  +		public void setFirstName(String firstName) {
  +			this.firstName = firstName;
  +		}
  +
  +	}
  +----
  +
  +In the preceding example, the following properties names can all be used:
  +
  +.relaxed binding
  +[cols="1,4"]
  +|===
  +| Property | Note
  +
  +|`acme.my-project.person.first-name`
  +|Kebab case, which is recommended for use in `.properties` and `.yml` files.
  +
  +|`acme.myProject.person.firstName`
  +|Standard camel case syntax.
  +
  +|`acme.my_project.person.first_name`
  +|Underscore notation, which is an alternative format for use in `.properties` and `.yml`
  +files.
  +
  +|`ACME_MYPROJECT_PERSON_FIRSTNAME`
  +|Upper case format, which is recommended when using system environment variables.
  +|===
  +
  +NOTE: The `prefix` value for the annotation _must_ be in kebab case (lowercase and
  +separated by `-`, such as `acme.my-project.person`).
  +
  +.relaxed binding rules per property source
  +[cols="2,4,4"]
  +|===
  +| Property Source | Simple | List
  +
  +|Properties Files
  +|Camel case, kebab case, or underscore notation
  +|Standard list syntax using `[ ]` or comma-separated values
  +
  +|YAML Files
  +|Camel case, kebab case, or underscore notation
  +|Standard YAML list syntax or comma-separated values
  +
  +|Environment Variables
  +|Upper case format with underscore as the delimiter. `_` should not be used within a
  +property name
  +|Numeric values surrounded by underscores, such as `MY_ACME_1_OTHER = my.acme[1].other`
  +
  +|System properties
  +|Camel case, kebab case, or underscore notation
  +|Standard list syntax using `[ ]` or comma-separated values
  +|===
  +
  +TIP: We recommend that, when possible, properties are stored in lower-case kebab format,
  +such as `my.property-name=acme`.
  +
   [[boot-features-external-config-complex-type-merge]]
  -==== Merging YAML Lists
  -As <<boot-features-external-config-loading-yaml,we showed earlier>>, any YAML content is
  -ultimately transformed to properties. That process may be counter-intuitive when
  -overriding "`list`" properties through a profile.
  +==== Merging Complex Types
  +When lists are configured in more than one place, overriding works by replacing the entire
  +list.
   
   For example, assume a `MyPojo` object with `name` and `description` attributes that are
   `null` by default. The following example exposes a list of `MyPojo` objects from
  
positive.code: 	  profiles: dev
  	acme:
  	  list:
          - name: my another name
  ----
  
  If the `dev` profile is not active, `AcmeProperties.list` contains one `MyPojo` entry,
  
negative.code: 	my.servers[1]=another.example.com
  ----
  
  To bind to properties like that by using Spring Boot's `Binder` utilities (which is what
  `@ConfigurationProperties` does), you need to have a property in the target bean of type
  `java.util.List` (or `Set`) and you either need to provide a setter or initialize it with
  a mutable value. For example, the following example binds to the properties shown
  