1C.Auto Config Mechanism
1C.Auto Config Mechanism
Take advantage of SpringBoot to complete the auto config.
1C.1.Naming and Rule
There are special features of Spring naming, mainly focused on the following (the directory structure will be explained in detail later)
/wings-conf/autoload, splitted config files/wings-i18n/autoload, splitted I18n files**/spring/boot/manual load, Boot-related config, likespring.facts**/spring/bean/produce bean, as specified by @ComponentScan**/spring/conf/Configurer or AutoConfiguration**/spring/prop/Property mapping**/spring/help/Configuration helper*Configuration.javaconditional load, with config items prefixed bywings.enabled.
When developing with idea, there will be yellow warnings or prompts, that do not affect the operation, but look like an eyesore.
- Prompting "Application context not configured for this file" Just add
boot/WingsAutoConfigurationmanually inProject Structure/Facets/Spring. - Prompting "annotation processing", check in
Settings/Annotation Processors/Enable annotation processing - Note: The inner classes in
@Configuration,static classare treated as independent and not bound by the outer.
In Wings project, there will be a wings-enabled.properties to toggle the feature. Set wings.enabled.silencer.verbose=true to view the INFO of the log message.
1C.2.Property Bind and Prompt
Properties classes are unified with *Prop.java and @Data, which can be auto prompted after configuration.
- manually add additional-spring-configuration-metadata.json
- auto-generated spring-configuration-metadata.json
References,
- https://docs.spring.io/spring-boot/docs/3.0.3/reference/htmlsingle/#appendix.configuration-metadata
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding
- https://github.com/spring-projects/spring-boot/wiki/IDE-binding-features#simple-pojo
1C.3.Configuring by Condition
- Configuration is
*Configuration.javain/spring/bean/ - Property is
*Prop.javain/spring/prop/ - Nested configurations do not inherit from
@Conditional- merged into
@ConditionalOnExpression - or customize a
@Conditional
- merged into
- multiple
@Conditionalareandlogic - multiple
Conditionareandlogic
Javadoc of Conditional
The
@Conditionalannotation may be used in any of the following ways:
- as a type-level annotation on any class directly or indirectly annotated with
@Component, including@Configurationclasses- as a meta-annotation, for the purpose of composing custom stereotype annotations
- as a method-level annotation on any
@BeanmethodIf a
@Configurationclass is marked with@Conditional,all of the@Beanmethods,@Importannotations, and@ComponentScanannotations associated with that class will be subject to the conditions.NOTE: Inheritance of
@Conditionalannotations is not supported; any conditions from superclasses or from overridden methods will not be considered.
1C.4.ConditionalOnClass No Effect
The following code, ConditionalOnClass placed on the same type of bean declaration, will report a NoClassDefFoundError
@Bean
@ConditionalOnClass(SomeService.class)
public SomeService someService() {
return new SomeService();
}Need to change to something like the following, inner class-driven configuration,
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(SomeService.class)
public static class SomeServiceConfiguration {
@Bean
public SomeService someService() {
return new SomeService();
}
}See Creating Your Own Auto-configuration
1C.5.Disable any @Component
In the Spring @Conditional auto configuration, the On*Bean depends on the registration order of the beans, which makes it difficult to detect problems. Therefore, in Wings, we move the problem to the early startup phase to detect bean conflicts as early as possible. By setting property files, we can disable unnecessary features.
On @Configuration, @Bean and any @Component, using @ConditionalWingsEnabled and the qualified-key can disable any Component and Bean,
qualified-key = Prefix. + ClassName + .beanMethod? = true|false
- Prefix - default wings.enabled
- ClassName - e.g. pro.fessional.wings.silencer.spring.boot.WingsEnabledCondition
- beanMethod - e.g. crc8Long
@*Configuration naming rules are as follows,
*AutoConfiguration-@AutoConfiguration@Import@Configuration*Configuration- top@Configurationand its@Bean*Event- inner@Configurationand its@EventListener*Wired- inner@Configurationand its@Autowired*Bean- inner@Configurationand wrap its single@Bean **Scan- inner@Configurationfor@ComponentScan
@ConditionalWingsEnabled has the following enhancements
- abs -
absolute-key, without prefix, priority lower thenqualified-key - key -
relative-key, with prefix, priority lower thenabsolute-key - value - default value, the lowest priority, if no key found
- and, not -
this && and1 && and2 && !not1 && !not2
where qualified-key is equivalent to id, globally unique and the highest priority, absolute-key and relative-key are equivalent to alias, can be shared without uniqueness. and the priority of these 3 keys is from highest to lowest.
- qualified-key =
prefix+ClassName+methodName? - absolute-key =
abs() - relative-key =
prefix+key() - default =
value()
In addition to the precise control of annotations, the following props can impl the ant-matcher control of qualified-key.
- wings.feature.error
- wings.feature.prefix
- wings.feature.enable
## ... is short for the package
## @ConditionalWingsEnabled(prefix = "catty.enabled")
## disable @Bean catBean in WingsEnabledCatConfiguration
catty.enabled.pro...WingsEnabledCatConfiguration.catBean=false
## disable InnerCatConfiguration and its Bean
catty.enabled.pro...WingsEnabledCatConfiguration$InnerCatConfiguration=false
## @Conditional(WingsEnabledCondition.class) or @ConditionalWingsEnabled
## disable @Bean dogBean in WingsEnabledDogConfiguration
wings.enabled.pro...WingsEnabledDogConfiguration.dogBean=false
## disable InnerDogConfiguration and its Bean
wings.enabled.pro...WingsEnabledDogConfiguration$InnerDogConfiguration=false1C.6. Feature Flags
The Wings FeatureFlags implementation has two levels, as follows.
- Config level -
@ConditionalWingsEnabledacts on the@Componentand@Bean. - Thread level -
FeatureFlagacts on the logical
The principle of both is the same, based on wings.feature and wings.enabled properties.
In business coding, toggling business logic can be achieved by using the following utility classes.
FeatureFlag- get the feature state using Class as keyTweakFeature- dynamically toggle feature at global or thread level
the priority of flag is as the following,
@ConditionalWingsEnabled- confClass or beanMethod- qualified-key =
prefix.+ClassName+.methodName? - absolute-key =
abs() - relative-key =
prefix.+key() - default =
value(), only if no prop and(), thennot()- only if this enabled
- qualified-key =
wings.enabled.*- string prop,one-onewings.feature.*- ant style prop,one-many, only if noone-oneFeatureFlag-TweakFeature, thenWingsEnabledContext
1C.7.Config Bean Order
Use the wings.reorder.* attribute, where * is.
beanName- one-to-one by name, high prioritybeanClass- one-to-many by type
The scope of its impact includes.
List<Bean>- injected ordered collection class.orderedStream()-ObjectProvider ordered stream
The ordering priority is as follows, NOTE, beans are declared or scanned in different mechanisms that affect priority.
wings.reorder.*configuration, highest priority- if
@Bean,@OrderoverOrdered - if
@Component,Orderedover@Order
this disabled if any of the followings,
- no property or no defined bean found
- wings.enabled.silencer.bean-reorder=false
also can set Primary by wings.primary.*, but only beanName is supported.
// wings.reorder.getterClass2 = 3
@Bean
public GetterClass getterClass2()
// wings.primary.testReorderServiceImpl2=true
// wings.reorder.testReorderServiceImpl2 = 3 # or
// wings.reorder.pro.fessional.wings.silencer.app.service.impl.TestReorderServiceImpl2=3
@Service
public class TestReorderServiceImpl2