Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The difference between Springboot1.x and 2.x in the implementation and usage of bean refresh custom properties through @ ConfigurationProperties

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "the difference between Springboot1.x and 2.x in the implementation and usage of bean refresh custom attributes through @ ConfigurationProperties". In daily operation, I believe that many people have doubts about the difference between Springboot1.x and 2.x in the implementation and usage of bean refresh custom attributes through @ ConfigurationProperties. The editor consulted all kinds of materials and sorted out simple and useful operation methods. I hope it will be helpful for you to answer the difference between Springboot1.x and 2.x on the implementation and usage of bean refresh custom properties through @ ConfigurationProperties! Next, please follow the editor to study!

A little understanding.

For springboot 1.x and 2.x configuration binding part of the source code principle understanding, briefly mentioned. Springboot has provided @ ConfigurationProperties annotation operation configuration class for loose binding (Relaxed Binding) since its release. What is interesting is that the specific implementation of Relaxed Binding in the two large versions is different. After reading some of the documents, I feel that springboot 2.0 wants to provide users with more stringent API, so it redesigns the way binding occurs. 2. 0 adds several new abstractions and develops a completely new binding API, while some of the old code in the old package is no longer used. The main points are as follows

1. PropertySources and ConfigurationPropertySources

You must be familiar with PropertySource, combined with the interface Environment, which is a PropertyResolver that allows you to parse properties from some underlying PropertySource implementations. The Spring framework provides PropertySource implementations for common configurations, such as system properties, command-line flags, and properties files. Spring Boot automatically configures these implementations (for example, loading application.properties) in a way that makes sense for most applications.

Instead of directly using the existing PropertySource interface for binding, Spring Boot 2.0 introduces a new ConfigurationPropertySource interface. It also provides a reasonable way to implement loosening binding rules, which used to be part of binders. The main API of this interface is very simple: ConfigurationProperty getConfigurationProperty (ConfigurationPropertyName name); there is also an IterableConfigurationPropertySource that implements the Iterable interface in disguise so that you can discover the configuration of all the names contained in the source.

You can get the external source data by using the following code Iterable sources = ConfigurationPropertySources.get (environment), or provide a simple MapConfigurationPropertySource implementation as needed, which is easy to use to restructure the source within the project.

2. The concrete realization of Relaxed Binding

In springboot 1.5 and 2.0, the binding logic for attributes and configuration values starts with the postProcessBeforeInitialization function of the ConfigurationPropertiesBindingPostProcessor class.

Taking a closer look at the source code in version 1.5, it is found that when the postProcessBeforeInitialization function is executed, the work of property value binding is delegated to the PropertiesConfigurationFactory class (this guy is something we can't find at all in 2.0, so we won't go into the details below)

When the version 2.0 postProcessBeforeInitialization function is called, the work of attribute value binding is delegated to the ConfigurationPropertiesBinder class and the bind function is called, but the ConfigurationPropertiesBinder class is not a public class. In fact, it is only an internal static class of ConfigurationPropertiesBindingPostProcessor, ostensibly responsible for handling the binding task of the @ ConfigurationProperties annotation. As you can see from the source code, the specific work is delegated to an object of another Binder class. The Binder class, added after SpringBoot 2.0, is the executor responsible for handling bindings between objects and multiple ConfigurationPropertySource, as we will see in later code examples.

So far, the difference in attribute configuration binding between basic springboot versions 1.x and 2.x simply shows that it is seven, seven, eight, eight, and then we start to fill in the hole from the use:

Scenario: signature request, the server needs to parse the signature field in the header information. The key of such fields must be defined in advance by the server, and the parsing process needs to be used repeatedly.

Signature header information class:

Data@ToString@ConfigurationProperties (prefix= "openapi.validate") public class SignatureHeaders {private static final String SIGNATURE_HEADERS_PREFIX = "openapi-validate-"; public static final Set SIGNATURE_PARAMETER_SET = new HashSet (); private static String HEADER_APPID = SIGNATURE_HEADERS_PREFIX + "appid"; private static String HEADER_TIMESTAMP = SIGNATURE_HEADERS_PREFIX + "timestamp"; private static String HEADER_NONCE = SIGNATURE_HEADERS_PREFIX + "nonce"; private static String HEADER_SIGNATURE = SIGNATURE_HEADERS_PREFIX + "signature" Static {SIGNATURE_PARAMETER_SET.add (HEADER_APPID); SIGNATURE_PARAMETER_SET.add (HEADER_TIMESTAMP); SIGNATURE_PARAMETER_SET.add (HEADER_NONCE); SIGNATURE_PARAMETER_SET.add (HEADER_SIGNATURE);} / * * assign appid * / private String appid; / * * assign appsecret * / private String appsecret / * * timestamp: ms * / private String timest / * * serial number / random string: at least 16 bits, prevent repeated submission during the validity period * / private String nonce; / * * signature * / private String signature;}

I. the use of 1.x

Parsing header information

/ / filter header information Map headerMap = Collections.list (request.getHeaderNames ()) .stream () .filter (headerName-> SignatureHeaders.HEADER_NAME_SET.contains (headerName)) .filter (Collectors.toMap (headerName-> headerName.replaceAll ("-", "."), headerName-> request.getHeader (headerName)); PropertySource propertySource = new MapPropertySource ("signatureHeaders", headerMap) SignatureHeaders signatureHeaders = RelaxedConfigurationBinder.with (SignatureHeaders.class) .setPropertySources (propertySource) .doBind ()

Bind helper class

Public class RelaxedConfigurationBinder {private final PropertiesConfigurationFactory factory; public RelaxedConfigurationBinder (T object) {this (new PropertiesConfigurationFactory (object));} public RelaxedConfigurationBinder (Class type) {this (new PropertiesConfigurationFactory (type));} public static RelaxedConfigurationBinder with (T object) {return new RelaxedConfigurationBinder (object);} public static RelaxedConfigurationBinder with (Class type) {return new RelaxedConfigurationBinder (type) } public RelaxedConfigurationBinder (PropertiesConfigurationFactory factory) {this.factory = factory; ConfigurationProperties properties = getMergedAnnotation (factory.getObjectType (), ConfigurationProperties.class); javax.validation.Validator validator = Validation.buildDefaultValidatorFactory (). GetValidator (); factory.setValidator (new SpringValidatorAdapter (validator)); factory.setConversionService (new DefaultConversionService ()); if (null! = properties) {factory.setIgnoreNestedProperties (properties.ignoreNestedProperties ()) Factory.setIgnoreInvalidFields (properties.ignoreInvalidFields ()); factory.setIgnoreUnknownFields (properties.ignoreUnknownFields ()); factory.setTargetName (properties.prefix ()); factory.setExceptionIfInvalid (properties.exceptionIfInvalid ());} public RelaxedConfigurationBinder setTargetName (String targetName) {factory.setTargetName (targetName); return this;} public RelaxedConfigurationBinder setPropertySources (PropertySource...) PropertySources) {MutablePropertySources sources = new MutablePropertySources (); for (PropertySource propertySource: propertySources) {sources.addLast (propertySource);} factory.setPropertySources (sources); return this;} public RelaxedConfigurationBinder setPropertySources (Environment environment) {factory.setPropertySources (ConfigurableEnvironment) environment). GetPropertySources ()); return this;} public RelaxedConfigurationBinder setPropertySources (PropertySources propertySources) {factory.setPropertySources (propertySources) Return this;} public RelaxedConfigurationBinder setConversionService (ConversionService conversionService) {factory.setConversionService (conversionService); return this;} public RelaxedConfigurationBinder setValidator (Validator validator) {factory.setValidator (validator); return this;} public RelaxedConfigurationBinder setResolvePlaceholders (boolean resolvePlaceholders) {factory.setResolvePlaceholders (resolvePlaceholders); return this } public T doBind () throws GeneralException {try {return factory.getObject ();} catch (Exception ex) {throw new GeneralException ("configuration binding failed!" , ex);}

Pit points mentioned earlier that PropertiesConfigurationFactory is needed in helper classes to specify settings such as configurationPropertySource, complete binding actions, and so on, while PropertiesConfigurationFactory does not exist in 2.x.

Second, the use of 2.x

Parsing header information

/ / filter header information Map headerMap = Collections.list (request.getHeaderNames ()) .stream () .filter (headerName-> SignatureHeaders.SIGNATURE_PARAMETER_SET.contains (headerName)) .filter (Collectors.toMap (headerName-> headerName.replaceAll ("-", ".), headerName-> request.getHeader (headerName); / / Custom ConfigurationProperty source information ConfigurationPropertySource sources = new MapConfigurationPropertySource (headerMap) / / create Binder binding class Binder binder = new Binder (sources); / / bind attribute SignatureHeaders signatureHeaders = binder.bind ("openapi.validate", Bindable.of (SignatureHeaders.class)) .get ()

2.x instead of building the attribute configuration factory, we implement the custom attribute configuration source through MapConfigurationPropertySource, then load the source information directly through the newly added binding class Binder, and bind to the bean attribute directly after identification, omitting a lot of initialization code from the code implementation.

2.x load external attribute configuration implementation:

/ / read from configuration file / configuration center / / environment can automatically inject or get Iterable sources = ConfigurationPropertySources.get (environment) directly in context; / / set BinderBinder binder = new Binder (sources); / / attribute binding SignatureHeaders signatureHeaders = binder.bind ("openapi.validate", Bindable.of (SignatureHeaders.class)) .get ()

Demo example: load the configuration property data of a custom Map into the header information class

@ RunWith (SpringRunner.class) @ SpringBootTest (classes = SignatureApp.class) @ Slf4jpublic class ConfigurationPropertyTest {@ Test public void testConfigurationPropertySources () {Map dataMap = new HashMap (); dataMap.put ("openapi.validate.appid", "123456789"); dataMap.put ("openapi.validate.timestamp", "1565062140111"); dataMap.put ("openapi.validate.nonce", "20190805180100102030") DataMap.put ("openapi.validate.signature", "vDMbihw6uaxlhoBCBJAY9xnejJXNCAA0QCc+I5X9EYYwAdccjNSB4L4mPZXymbH+fwm3ulkuY7UBNZclV1OBoELCSUMn7VRLAVqBS4bKrTA="); ConfigurationPropertySource sources = new MapConfigurationPropertySource (dataMap); Binder binder = new Binder (sources); SignatureHeaders signatureHeaders = binder.bind ("openapi.validate", Bindable.of (SignatureHeaders.class)). Get (); log.info ("# # Parse Result: {}", signatureHeaders);}}

At this point, on the "Springboot1.x and 2.x through @ ConfigurationProperties to refresh the custom properties of bean implementation methods and usage differences" is over, I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report