Commit 5ea92a89 authored by liaozan's avatar liaozan 🏀

Refactor auto configuration property loading

parent cdcdefb2
......@@ -16,51 +16,51 @@ import static java.util.stream.Collectors.*;
@Slf4j
public class StreamUtils {
public static <T> List<T> filterToList(Collection<T> data, Predicate<T> predicate) {
public static <T> List<T> filterToList(Iterable<T> data, Predicate<T> predicate) {
return filter(data, predicate, Collectors.toList());
}
public static <T> Set<T> filterToSet(Collection<T> data, Predicate<T> predicate) {
public static <T> Set<T> filterToSet(Iterable<T> data, Predicate<T> predicate) {
return filter(data, predicate, Collectors.toSet());
}
public static <T, C extends Collection<T>> C filter(Collection<T> data, Predicate<T> predicate, Collector<T, ?, C> collector) {
return Optional.ofNullable(data).orElse(emptyList()).stream().filter(predicate).collect(collector);
public static <T, C extends Iterable<T>> C filter(Iterable<T> data, Predicate<T> predicate, Collector<T, ?, C> collector) {
return from(data).filter(predicate).collect(collector);
}
public static <T, E> List<E> toList(Collection<T> data, Function<T, E> mapper) {
public static <T, E> List<E> toList(Iterable<T> data, Function<T, E> mapper) {
return toList(data, mapper, false);
}
public static <T, E> List<E> toList(Collection<T> data, Function<T, E> mapper, boolean distinct) {
public static <T, E> List<E> toList(Iterable<T> data, Function<T, E> mapper, boolean distinct) {
return toList(data, mapper, distinct, false);
}
public static <T, E> List<E> toList(Collection<T> data, Function<T, E> mapper, boolean distinct, boolean ignoreNull) {
public static <T, E> List<E> toList(Iterable<T> data, Function<T, E> mapper, boolean distinct, boolean ignoreNull) {
return extract(data, mapper, distinct, ignoreNull, Collectors.toList());
}
public static <T, E> Set<E> toSet(Collection<T> data, Function<T, E> mapper) {
public static <T, E> Set<E> toSet(Iterable<T> data, Function<T, E> mapper) {
return toSet(data, mapper, false);
}
public static <T, E> Set<E> toSet(Collection<T> data, Function<T, E> mapper, boolean ignoreNull) {
public static <T, E> Set<E> toSet(Iterable<T> data, Function<T, E> mapper, boolean ignoreNull) {
return extract(data, mapper, ignoreNull, false, Collectors.toSet());
}
public static <K, T> Map<K, T> toMap(Collection<T> data, Function<T, K> keyMapper) {
public static <K, T> Map<K, T> toMap(Iterable<T> data, Function<T, K> keyMapper) {
return toMap(data, keyMapper, false);
}
public static <K, T> Map<K, T> toMap(Collection<T> data, Function<T, K> keyMapper, boolean ordered) {
public static <K, T> Map<K, T> toMap(Iterable<T> data, Function<T, K> keyMapper, boolean ordered) {
return toMap(data, keyMapper, Function.identity(), ordered);
}
public static <K, T, V> Map<K, V> toMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
public static <K, T, V> Map<K, V> toMap(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
return toMap(data, keyMapper, valueMapper, false);
}
public static <K, T, V> Map<K, V> toMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, boolean ordered) {
public static <K, T, V> Map<K, V> toMap(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, boolean ordered) {
Supplier<Map<K, V>> mapFactory = HashMap::new;
if (ordered) {
mapFactory = LinkedHashMap::new;
......@@ -68,74 +68,67 @@ public class StreamUtils {
return toMap(data, keyMapper, valueMapper, mapFactory);
}
public static <K, T, V, M extends Map<K, V>> Map<K, V> toMap(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Supplier<M> mapFactory) {
return Optional.ofNullable(data)
.orElse(emptyList())
.stream()
.collect(Collectors.toMap(keyMapper, valueMapper, (oldValue, newValue) -> {
// Could not get the key when mergeFunction invoke
log.warn("There are multiple values with the same key when toMap, return the old one");
return oldValue;
}, mapFactory));
public static <K, T, V, M extends Map<K, V>> Map<K, V> toMap(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Supplier<M> mapFactory) {
return from(data).collect(Collectors.toMap(keyMapper, valueMapper, (oldValue, newValue) -> {
// Could not get the key when mergeFunction invoke
log.warn("There are multiple values with the same key when toMap, return the old one");
return oldValue;
}, mapFactory));
}
public static <K, T> Map<K, List<T>> groupBy(Collection<T> data, Function<T, K> mapper) {
public static <K, T> Map<K, List<T>> groupBy(Iterable<T> data, Function<T, K> mapper) {
return groupBy(data, mapper, false);
}
public static <K, T> Map<K, List<T>> groupBy(Collection<T> data, Function<T, K> keyMapper, boolean ignoreNullKey) {
public static <K, T> Map<K, List<T>> groupBy(Iterable<T> data, Function<T, K> keyMapper, boolean ignoreNullKey) {
return groupBy(data, keyMapper, Collectors.toList(), ignoreNullKey);
}
public static <K, T, V> Map<K, V> groupBy(Collection<T> data, Function<T, K> mapper, Collector<T, ?, V> collectors) {
public static <K, T, V> Map<K, V> groupBy(Iterable<T> data, Function<T, K> mapper, Collector<T, ?, V> collectors) {
return groupBy(data, mapper, collectors, false);
}
public static <K, T, V> Map<K, V> groupBy(Collection<T> data, Function<T, K> mapper, Collector<T, ?, V> collectors, boolean ignoreNullKey) {
public static <K, T, V> Map<K, V> groupBy(Iterable<T> data, Function<T, K> mapper, Collector<T, ?, V> collectors, boolean ignoreNullKey) {
return groupBy(data, mapper, Function.identity(), collectors, ignoreNullKey);
}
public static <K, T, V> Map<K, List<V>> groupBy(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
public static <K, T, V> Map<K, List<V>> groupBy(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper) {
return groupBy(data, keyMapper, valueMapper, Collectors.toList(), false);
}
public static <K, T, V> Map<K, List<V>> groupBy(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, boolean ignoreNullKey) {
public static <K, T, V> Map<K, List<V>> groupBy(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, boolean ignoreNullKey) {
return groupBy(data, keyMapper, valueMapper, Collectors.toList(), ignoreNullKey);
}
public static <K, T, V, C> Map<K, C> groupBy(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Collector<V, ?, C> collector) {
public static <K, T, V, C> Map<K, C> groupBy(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Collector<V, ?, C> collector) {
return groupBy(data, keyMapper, valueMapper, collector, false);
}
public static <K, T, V, C> Map<K, C> groupBy(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Collector<V, ?, C> collector, boolean ignoreNullKey) {
public static <K, T, V, C> Map<K, C> groupBy(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Collector<V, ?, C> collector, boolean ignoreNullKey) {
return groupBy(data, keyMapper, valueMapper, collector, ignoreNullKey, HashMap::new);
}
public static <K, T, V, C> Map<K, C> groupBy(Collection<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Collector<V, ?, C> collector, boolean ignoreNullKey, Supplier<Map<K, C>> mapSupplier) {
Stream<T> stream = Optional.ofNullable(data)
.orElse(emptyList())
.stream();
public static <K, T, V, C> Map<K, C> groupBy(Iterable<T> data, Function<T, K> keyMapper, Function<T, V> valueMapper, Collector<V, ?, C> collector, boolean ignoreNullKey, Supplier<Map<K, C>> mapSupplier) {
Stream<T> stream = from(data);
if (ignoreNullKey) {
stream = stream.filter(item -> null != keyMapper.apply(item));
}
return stream.collect(groupingBy(keyMapper, mapSupplier, mapping(valueMapper, collector)));
}
public static <T> String join(Collection<T> data, CharSequence delimiter) {
public static <T> String join(Iterable<T> data, CharSequence delimiter) {
return join(data, delimiter, Objects::toString);
}
public static <T> String join(Collection<T> data, CharSequence delimiter, Function<T, ? extends CharSequence> toStringFunction) {
public static <T> String join(Iterable<T> data, CharSequence delimiter, Function<T, ? extends CharSequence> toStringFunction) {
return join(data, delimiter, "", "", toStringFunction);
}
public static <T> String join(Collection<T> data, CharSequence delimiter, String prefix, String suffix, Function<T, ? extends CharSequence> toStringFunction) {
return Optional.ofNullable(data)
.orElse(emptyList())
.stream().map(toStringFunction).collect(joining(delimiter, prefix, suffix));
public static <T> String join(Iterable<T> data, CharSequence delimiter, String prefix, String suffix, Function<T, ? extends CharSequence> toStringFunction) {
return from(data).map(toStringFunction).collect(joining(delimiter, prefix, suffix));
}
public static <T, E, R> R extract(Collection<T> data, Function<T, E> mapper, boolean distinct, boolean ignoreNull, Collector<E, ?, R> collector) {
public static <T, E, R> R extract(Iterable<T> data, Function<T, E> mapper, boolean distinct, boolean ignoreNull, Collector<E, ?, R> collector) {
Predicate<E> predicate = null;
if (ignoreNull) {
predicate = Objects::nonNull;
......@@ -143,11 +136,8 @@ public class StreamUtils {
return extract(data, mapper, predicate, distinct, collector);
}
public static <T, E, R> R extract(Collection<T> data, Function<T, E> mapper, Predicate<E> predicate, boolean distinct, Collector<E, ?, R> collector) {
Stream<E> stream = Optional.ofNullable(data)
.orElse(emptyList())
.stream()
.map(mapper);
public static <T, E, R> R extract(Iterable<T> data, Function<T, E> mapper, Predicate<E> predicate, boolean distinct, Collector<E, ?, R> collector) {
Stream<E> stream = from(data).map(mapper);
if (distinct) {
stream = stream.distinct();
}
......@@ -157,4 +147,13 @@ public class StreamUtils {
return stream.collect(collector);
}
public static <T> Stream<T> from(Iterable<T> iterable) {
return from(iterable, false);
}
public static <T> Stream<T> from(Iterable<T> iterable, boolean parallel) {
Iterable<T> source = Optional.ofNullable(iterable).orElse(emptyList());
return StreamSupport.stream(source.spliterator(), parallel);
}
}
\ No newline at end of file
package com.schbrain.common.util.properties;
import com.schbrain.common.util.ConfigurationPropertiesUtils;
import org.springframework.core.env.MapPropertySource;
import java.util.LinkedHashMap;
import java.util.Map;
/**
......@@ -13,12 +13,12 @@ import java.util.Map;
*/
public class SchbrainMapPropertySource extends MapPropertySource {
public SchbrainMapPropertySource(String name, Object source) {
this(name, ConfigurationPropertiesUtils.toMap(source));
public SchbrainMapPropertySource(String name, Map<String, String> source) {
super(name, new LinkedHashMap<>(source));
}
public SchbrainMapPropertySource(String name, Map<String, Object> source) {
super(name, source);
public void addProperties(Map<String, String> properties) {
getSource().putAll(properties);
}
}
\ No newline at end of file
......@@ -2,55 +2,39 @@ package com.schbrain.common.util.support;
import com.schbrain.common.util.ConfigurationPropertiesUtils;
import lombok.Data;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.BindHandler;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.bind.*;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import java.beans.Introspector;
/**
* <b> WARNING!!! </b>
* <p>
* If you want to use a subclass of this class before {@link BeanPostProcessor},
* please load it through {@link com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils}
*
* @author liaozan
* @since 2022/1/10
*/
@Data
public abstract class ConfigurableProperties {
public abstract class ConfigurableProperties implements Ordered {
/**
* the namespace of remote config
*/
protected String namespace = getDefaultNamespace();
/**
* the prefix of properties
* get the namespace of remote config
*/
protected String prefix = getPossiblePrefix();
public abstract String getDefaultNamespace();
/**
* the name of propertySource
* bind properties
*/
protected String name = Introspector.decapitalize(getClass().getSimpleName());
public String getDefaultNamespace() {
return "application";
}
@SuppressWarnings({"unchecked", "unused"})
public <T extends ConfigurableProperties> T bindOrCreate(ConfigurableEnvironment environment, boolean afterMerge) {
return (T) Binder.get(environment, bindHandler()).bindOrCreate(getPrefix(), getClass());
public ConfigurableProperties bind(ConfigurableEnvironment environment) {
return Binder.get(environment, bindHandler()).bindOrCreate(getPropertiesPrefix(), Bindable.ofInstance(this));
}
protected BindHandler bindHandler() {
return BindHandler.DEFAULT;
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
private String getPossiblePrefix() {
/**
* the prefix of properties
*/
protected String getPropertiesPrefix() {
ConfigurationProperties annotation = getClass().getAnnotation(ConfigurationProperties.class);
if (annotation == null) {
String className = ConfigurationProperties.class.getName();
......@@ -60,4 +44,11 @@ public abstract class ConfigurableProperties {
return ConfigurationPropertiesUtils.getPrefix(getClass());
}
/**
* get the {@link org.springframework.boot.context.properties.bind.BindHandler} for bind
*/
protected BindHandler bindHandler() {
return BindHandler.DEFAULT;
}
}
\ No newline at end of file
......@@ -9,10 +9,10 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface IgnoreLogin {
/**
* 是否忽略登录
* @return
*/
boolean ignore() default true;
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
......
......@@ -34,21 +34,6 @@
"description": "encoding for request\/response",
"sourceType": "com.schbrain.common.web.properties.WebProperties"
},
{
"name": "schbrain.web.name",
"type": "java.lang.String",
"sourceType": "com.schbrain.common.web.properties.WebProperties"
},
{
"name": "schbrain.web.namespace",
"type": "java.lang.String",
"sourceType": "com.schbrain.common.web.properties.WebProperties"
},
{
"name": "schbrain.web.prefix",
"type": "java.lang.String",
"sourceType": "com.schbrain.common.web.properties.WebProperties"
},
{
"name": "schbrain.web.wrap-response",
"type": "java.lang.Boolean",
......
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.common.web.properties.WebProperties
\ No newline at end of file
......@@ -26,7 +26,7 @@
</build>
```
**Second** specify build-script repository.
**Second** specify build-script repository.
```.xml
<configuration>
......@@ -56,4 +56,4 @@ The completion config like this:
</plugin>
</plugins>
</build>
```
```
\ No newline at end of file
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
......
......@@ -52,6 +52,8 @@
<schbrain-common-util.version>${revision}</schbrain-common-util.version>
<schbrain-common.version>${revision}</schbrain-common.version>
<schbrain-dubbo.version>${revision}</schbrain-dubbo.version>
<schbrain-elasticsearch.version>${revision}</schbrain-elasticsearch.version>
<schbrain-kafka.version>${revision}</schbrain-kafka.version>
<schbrain-logger.version>${revision}</schbrain-logger.version>
<schbrain-module-tree.version>${revision}</schbrain-module-tree.version>
<schbrain-mybatis.version>${revision}</schbrain-mybatis.version>
......@@ -151,8 +153,13 @@
<!-- 二方包 -->
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>schbrain-spring-support</artifactId>
<version>${schbrain-spring-support.version}</version>
<artifactId>apollo-spring-boot-starter</artifactId>
<version>${schbrain-apollo.version}</version>
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>cache-spring-boot-starter</artifactId>
<version>${schbrain-cache.version}</version>
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
......@@ -161,19 +168,24 @@
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${schbrain-mybatis.version}</version>
<artifactId>elasticsearch-spring-boot-starter</artifactId>
<version>${schbrain-elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>apollo-spring-boot-starter</artifactId>
<version>${schbrain-apollo.version}</version>
<artifactId>kafka-spring-boot-starter</artifactId>
<version>${schbrain-kafka.version}</version>
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>logger-spring-boot-starter</artifactId>
<version>${schbrain-logger.version}</version>
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${schbrain-mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>oss-spring-boot-starter</artifactId>
......@@ -186,13 +198,13 @@
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>cache-spring-boot-starter</artifactId>
<version>${schbrain-cache.version}</version>
<artifactId>schbrain-base-dao</artifactId>
<version>${schbrain-base-dao.version}</version>
</dependency>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>schbrain-base-dao</artifactId>
<version>${schbrain-base-dao.version}</version>
<artifactId>schbrain-spring-support</artifactId>
<version>${schbrain-spring-support.version}</version>
</dependency>
<!-- 三方包 -->
......@@ -650,6 +662,32 @@
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-configuration-metadata</id>
<phase>compile</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${project.build.outputDirectory}/META-INF</directory>
<includes>
<include>spring-configuration-metadata.json</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<outputDirectory>${project.basedir}/src/main/resources/META-INF</outputDirectory>
<overwrite>true</overwrite>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
......
package com.schbrain.framework.autoconfigure.apollo;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration;
import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;
import com.schbrain.framework.autoconfigure.apollo.properties.ApolloProperties;
import com.schbrain.framework.autoconfigure.apollo.properties.ConfigurationPropertiesRegistry;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
......@@ -15,10 +13,10 @@ import org.springframework.context.annotation.Import;
* @since 2021/11/15
*/
@EnableApolloConfig
@Import({SchbrainPropertySourcesProcessor.class, ConfigurationPropertiesRegistry.class})
@Import(ConfigurationPropertiesRegistry.class)
@EnableConfigurationProperties(ApolloProperties.class)
@AutoConfiguration(before = ApolloAutoConfiguration.class)
@AutoConfiguration(before = com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration.class)
@ConditionalOnProperty(value = PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, matchIfMissing = true)
public class SchbrainApolloAutoConfiguration {
public class ApolloAutoConfiguration {
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.properties;
package com.schbrain.framework.autoconfigure.apollo;
import com.ctrip.framework.foundation.Foundation;
import com.schbrain.common.util.ApplicationName;
import com.schbrain.common.util.EnvUtils;
import com.schbrain.framework.support.spring.EnvironmentPostProcessorAdapter;
import com.schbrain.framework.support.spring.EnvironmentPostProcessorLoggerAwareAdapter;
import com.schbrain.framework.support.spring.defaults.DefaultPropertiesEnvironmentPostProcessor;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
......@@ -24,34 +23,37 @@ import static com.ctrip.framework.apollo.spring.config.PropertySourcesConstants.
* @author liaozan
* @since 2021/11/6
*/
public class ApolloPropertiesPreparer extends EnvironmentPostProcessorAdapter implements Ordered {
public class ApolloConfigurationInitializer extends EnvironmentPostProcessorLoggerAwareAdapter implements Ordered {
// get properties after configData loaded
public static final Integer ORDER = ConfigDataEnvironmentPostProcessor.ORDER + 1;
public static final String ENV_KEY = "env";
private static final Map<String, Object> INIT_PROPERTIES = new LinkedHashMap<>();
/**
* load properties after set the default properties
*/
public static final Integer DEFAULT_ORDER = DefaultPropertiesEnvironmentPostProcessor.DEFAULT_ORDER + 1;
public ApolloPropertiesPreparer(DeferredLogFactory deferredLogFactory, ConfigurableBootstrapContext bootstrapContext) {
private static final String ENV_KEY = "env";
private static Map<String, Object> INIT_PROPERTIES = new LinkedHashMap<>();
private final ConfigurablePropertiesLoader configurablePropertiesLoader;
public ApolloConfigurationInitializer(DeferredLogFactory deferredLogFactory, ConfigurableBootstrapContext bootstrapContext) {
super(deferredLogFactory, bootstrapContext);
this.configurablePropertiesLoader = new ConfigurablePropertiesLoader(getDeferredLogFactory());
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
if (disabled(environment)) {
print("apollo is disabled");
print(APOLLO_BOOTSTRAP_ENABLED + " is disabled");
return;
}
setRequiredProperty(environment);
configurablePropertiesLoader.load(environment, application);
}
@Override
public int getOrder() {
return ORDER;
}
@Override
protected void onBootstrapContextClosed(ConfigurableApplicationContext context) {
context.getBeanFactory().addBeanPostProcessor(new ConfigurablePropertiesBeanPostProcessor(context));
return DEFAULT_ORDER;
}
private boolean disabled(ConfigurableEnvironment environment) {
......@@ -71,8 +73,11 @@ public class ApolloPropertiesPreparer extends EnvironmentPostProcessorAdapter im
saveProperty(APOLLO_BOOTSTRAP_EAGER_LOAD_ENABLED, true);
saveProperty(APOLLO_BOOTSTRAP_ENABLED, true);
saveProperty(APOLLO_CACHE_FILE_ENABLE, true);
saveProperty(APOLLO_PROPERTY_ORDER_ENABLE, true);
saveProperty(APOLLO_PROPERTY_NAMES_CACHE_ENABLE, true);
// DO NOT set to true. After caching the property name, SpringBoot may not be able to bind the properties
saveProperty(APOLLO_PROPERTY_NAMES_CACHE_ENABLE, false);
saveProperty(APOLLO_OVERRIDE_SYSTEM_PROPERTIES, false);
printProperties();
}
......@@ -84,6 +89,7 @@ public class ApolloPropertiesPreparer extends EnvironmentPostProcessorAdapter im
private void printProperties() {
INIT_PROPERTIES.forEach((k, v) -> print(k + " : " + v));
INIT_PROPERTIES = null;
}
private void print(String message) {
......@@ -120,7 +126,11 @@ public class ApolloPropertiesPreparer extends EnvironmentPostProcessorAdapter im
}
private String getEnv(ConfigurableEnvironment environment) {
return EnvUtils.getProfile(environment);
String profile = EnvUtils.getProfile(environment);
if (profile == null) {
profile = EnvUtils.DEVELOPMENT;
}
return profile;
}
private String getAppId(ConfigurableEnvironment environment) {
......
......@@ -12,7 +12,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
* @since 2022/4/19
*/
@Order(ApolloApplicationContextInitializer.DEFAULT_ORDER + 1)
public class SchbrainApolloPropertiesEnvironmentPostProcessor implements EnvironmentPostProcessor {
public class ApolloPropertiesReorderEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
......
package com.schbrain.framework.autoconfigure.apollo;
import cn.hutool.core.thread.GlobalThreadPool;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.schbrain.common.util.properties.SchbrainMapPropertySource;
import com.schbrain.common.util.support.ConfigurableProperties;
import com.schbrain.framework.autoconfigure.apollo.listener.PropertiesPreparedEvent;
import com.schbrain.framework.autoconfigure.apollo.listener.PropertiesPreparedEventListener;
import com.schbrain.framework.autoconfigure.apollo.properties.ApolloProperties;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.logging.Log;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ClassUtils;
import java.util.List;
import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactories;
/**
* @author liaozan
* @since 2023-04-29
*/
class ConfigurablePropertiesLoader {
/**
* the name of properties propertySource
*/
private static final String PROPERTIES_PROPERTY_SOURCE = "ConfigurablePropertiesPropertySource";
private final Log log;
ConfigurablePropertiesLoader(DeferredLogFactory logFactory) {
this.log = logFactory.getLog(ConfigurablePropertiesLoader.class);
}
void load(ConfigurableEnvironment environment, SpringApplication application) {
List<ConfigurableProperties> configurableProperties = loadFactories(ConfigurableProperties.class, getClass().getClassLoader());
if (CollectionUtils.isEmpty(configurableProperties)) {
log.warn("There is no configuration properties found");
return;
}
ApplicationEventMulticaster eventMulticaster = createEventMulticaster(application);
ApolloProperties apolloProperties = ApolloProperties.get(environment);
// MUST NOT use CachedCompositePropertySource
CompositePropertySource compositePropertySource = new CompositePropertySource(PROPERTIES_PROPERTY_SOURCE);
if (apolloProperties.isRemoteFirst()) {
environment.getPropertySources().addFirst(compositePropertySource);
} else {
environment.getPropertySources().addLast(compositePropertySource);
}
configurableProperties.forEach(properties -> {
String namespace = properties.getDefaultNamespace();
Config config = ConfigService.getConfig(namespace);
SchbrainMapPropertySource propertySource = ConfigUtils.toPropertySource(namespace, config);
if (propertySource == null) {
log.warn("No configuration properties loaded under namespace: " + namespace);
return;
}
ConfigUtils.resolvePlaceHolders(environment, propertySource);
// early add to environment to support properties bind
compositePropertySource.addPropertySource(propertySource);
ConfigurableProperties boundProperties = properties.bind(environment);
eventMulticaster.multicastEvent(new PropertiesPreparedEvent(boundProperties, propertySource, environment, application));
});
}
private ApplicationEventMulticaster createEventMulticaster(SpringApplication application) {
SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
eventMulticaster.setTaskExecutor(GlobalThreadPool.getExecutor());
for (ApplicationListener<?> listener : application.getListeners()) {
if (ClassUtils.isAssignableValue(PropertiesPreparedEventListener.class, listener)) {
eventMulticaster.addApplicationListener(listener);
}
}
return eventMulticaster;
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.properties;
package com.schbrain.framework.autoconfigure.apollo;
import cn.hutool.core.text.StrPool;
import com.ctrip.framework.apollo.spring.property.SpringValue;
......
package com.schbrain.framework.autoconfigure.apollo;
import com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor;
import com.schbrain.framework.autoconfigure.apollo.util.PropertySourceOrderUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* @author liaozan
* @since 2021/12/6
*/
public class SchbrainPropertySourcesProcessor extends PropertySourcesProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
super.postProcessBeanFactory(beanFactory);
PropertySourceOrderUtils.adjustPropertySourceOrder(beanFactory.getBean(ConfigurableEnvironment.class));
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.listener;
import com.schbrain.common.util.properties.SchbrainMapPropertySource;
import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Getter;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationEvent;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* @author liaozan
* @since 2023-04-28
*/
@Getter
public class PropertiesPreparedEvent extends ApplicationEvent {
private static final long serialVersionUID = 2567291189881702459L;
private final ConfigurableEnvironment environment;
private final SchbrainMapPropertySource propertySource;
private final SpringApplication application;
public PropertiesPreparedEvent(ConfigurableProperties properties, SchbrainMapPropertySource propertySource,
ConfigurableEnvironment environment, SpringApplication application) {
super(properties);
this.environment = environment;
this.propertySource = propertySource;
this.application = application;
}
public ConfigurableProperties getConfigurableProperties() {
return (ConfigurableProperties) getSource();
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.listener;
import org.springframework.context.ApplicationListener;
/**
* @author liaozan
* @since 2023-04-29
*/
public interface PropertiesPreparedEventListener extends ApplicationListener<PropertiesPreparedEvent> {
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.listener;
import com.schbrain.common.util.support.ConfigurableProperties;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* @author liaozan
* @since 2023-04-28
*/
@SuppressWarnings("unchecked")
public class PropertiesPreparedEventListenerAdapter<T extends ConfigurableProperties> implements PropertiesPreparedEventListener {
private final Class<T> propertyType;
public PropertiesPreparedEventListenerAdapter() {
ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
this.propertyType = (Class<T>) actualTypeArguments[0];
}
@Override
public void onApplicationEvent(PropertiesPreparedEvent event) {
if (event.getConfigurableProperties().getClass() == propertyType) {
onPropertiesPrepared(event, (T) event.getConfigurableProperties());
}
}
protected void onPropertiesPrepared(PropertiesPreparedEvent event, T configurableProperties) {
}
}
\ No newline at end of file
......@@ -25,4 +25,4 @@ public class ApolloProperties {
return Binder.get(environment).bindOrCreate(PREFIX, ApolloProperties.class);
}
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.properties;
import com.schbrain.common.util.support.ConfigurableProperties;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import com.schbrain.framework.support.spring.BeanPostProcessorAdapter;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @author liaozan
* @since 2022/9/16
*/
public class ConfigurablePropertiesBeanPostProcessor extends BeanPostProcessorAdapter<ConfigurableProperties> {
public ConfigurablePropertiesBeanPostProcessor(ConfigurableApplicationContext applicationContext) {
this.setApplicationContext(applicationContext);
}
@Override
protected ConfigurableProperties doPostProcessBeforeInstantiation(Class<ConfigurableProperties> beanClass) {
return ConfigUtils.loadConfig(environment, beanClass);
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.util;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import com.schbrain.common.util.ConfigurationPropertiesUtils;
import com.google.common.collect.Maps;
import com.schbrain.common.util.properties.SchbrainMapPropertySource;
import com.schbrain.common.util.support.ConfigurableProperties;
import com.schbrain.framework.autoconfigure.apollo.properties.ApolloProperties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.DefaultPropertiesPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.core.env.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.LinkedHashMap;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Map.Entry;
import static com.ctrip.framework.apollo.core.ApolloClientSystemConsts.APP_ID;
import java.util.Set;
/**
* @author liaozan
* @since 2021/12/6
*/
@Slf4j
public class ConfigUtils {
private static final Log LOGGER = LogFactory.getLog(ConfigUtils.class);
private static final boolean APOLLO_DISABLED = System.getProperty(APP_ID) == null;
public static boolean isApolloDisabled() {
return APOLLO_DISABLED;
}
public static <T extends ConfigurableProperties> T loadConfig(ConfigurableEnvironment environment, Class<T> propertyClass) {
// load default and local properties
T target = BeanUtils.instantiateClass(propertyClass).bindOrCreate(environment, false);
Map<String, Object> defaultProperties = ConfigurationPropertiesUtils.toMap(target);
// load remote config
Map<String, Object> loadedProperties = loadConfig(target.getNamespace(), target.getPrefix());
// merge
ApolloProperties apolloProperties = ApolloProperties.get(environment);
Map<String, Object> mergedProperties = mergeProperties(loadedProperties, defaultProperties, apolloProperties.isRemoteFirst());
// add to environment
addToEnvironment(environment, target.getName(), mergedProperties);
// rebind after addToEnvironment
return target.bindOrCreate(environment, true);
}
public static Map<String, Object> loadConfig(String namespace) {
return loadConfig(namespace, null);
}
public static Map<String, Object> loadConfig(String namespace, String prefix) {
if (isApolloDisabled()) {
return new LinkedHashMap<>();
}
Config config = ConfigService.getConfig(namespace);
if (config.getSourceType() == ConfigSourceType.LOCAL) {
LOGGER.warn(String.format("Failed to get config from Apollo namespace: %s, will use the local cache value", namespace));
}
Map<String, Object> configs = new LinkedHashMap<>();
for (String propertyName : config.getPropertyNames()) {
if (prefix != null) {
if (!propertyName.startsWith(prefix)) {
continue;
}
}
String propertyValue = config.getProperty(propertyName, null);
configs.put(propertyName, propertyValue);
@Nullable
public static SchbrainMapPropertySource toPropertySource(String name, Config config) {
Set<String> propertyNames = config.getPropertyNames();
if (propertyNames.isEmpty()) {
return null;
}
return configs;
}
public static <T extends ConfigurableProperties> void addToEnvironment(ConfigurableEnvironment environment, T properties) {
addToEnvironment(environment, new SchbrainMapPropertySource(properties.getName(), properties));
}
public static void addToEnvironment(ConfigurableEnvironment environment, String name, Map<String, Object> properties) {
addToEnvironment(environment, new SchbrainMapPropertySource(name, properties));
}
public static void addToEnvironment(ConfigurableEnvironment environment, MapPropertySource propertySource) {
MutablePropertySources propertySources = environment.getPropertySources();
String propertySourceName = propertySource.getName();
boolean alreadyExist = propertySources.contains(propertySourceName);
if (alreadyExist) {
PropertySource<?> existing = propertySources.get(propertySourceName);
if (existing instanceof MapPropertySource) {
Map<String, Object> existingSource = ((MapPropertySource) existing).getSource();
existingSource.putAll(propertySource.getSource());
} else {
LOGGER.warn("Existing propertySource is not an instance of MapPropertySource, overwrite existing...");
propertySources.replace(propertySourceName, propertySource);
}
} else {
propertySources.addLast(propertySource);
Map<String, String> configs = Maps.newLinkedHashMapWithExpectedSize(propertyNames.size());
for (String propertyName : propertyNames) {
String property = config.getProperty(propertyName, null);
configs.put(propertyName, property);
}
resolvePlaceHolders(environment, propertySource);
ConfigurationPropertySources.attach(environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
return new SchbrainMapPropertySource(name, configs);
}
public static void resolvePlaceHolders(ConfigurableEnvironment environment, MapPropertySource propertySource) {
public static void resolvePlaceHolders(ConfigurableEnvironment environment, SchbrainMapPropertySource propertySource) {
Map<String, Object> source = propertySource.getSource();
for (Entry<String, Object> entry : source.entrySet()) {
Object value = entry.getValue();
......@@ -116,18 +43,4 @@ public class ConfigUtils {
}
}
private static Map<String, Object> mergeProperties(Map<String, Object> loadedProperties,
Map<String, Object> defaultProperties,
boolean remoteFirst) {
Map<String, Object> mergedProperties;
if (remoteFirst) {
defaultProperties.putAll(loadedProperties);
mergedProperties = defaultProperties;
} else {
loadedProperties.putAll(defaultProperties);
mergedProperties = loadedProperties;
}
return mergedProperties;
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.apollo.util;
import com.schbrain.framework.autoconfigure.apollo.properties.ApolloProperties;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.boot.DefaultPropertiesPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.core.env.*;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Set;
......@@ -47,7 +46,6 @@ public class PropertySourceOrderUtils {
// Make sure the default configurations always in the end
DefaultPropertiesPropertySource.moveToEnd(environment);
ConfigurationPropertySources.attach(environment);
}
}
\ No newline at end of file
org.springframework.boot.env.EnvironmentPostProcessor=\
com.schbrain.framework.autoconfigure.apollo.properties.ApolloPropertiesPreparer,\
com.schbrain.framework.autoconfigure.apollo.SchbrainApolloPropertiesEnvironmentPostProcessor
\ No newline at end of file
com.schbrain.framework.autoconfigure.apollo.ApolloConfigurationInitializer,\
com.schbrain.framework.autoconfigure.apollo.ApolloPropertiesReorderEnvironmentPostProcessor
\ No newline at end of file
com.schbrain.framework.autoconfigure.apollo.SchbrainApolloAutoConfiguration
\ No newline at end of file
com.schbrain.framework.autoconfigure.apollo.ApolloAutoConfiguration
\ No newline at end of file
......@@ -3,7 +3,7 @@ package com.schbrain.framework.autoconfigure.cache;
import com.schbrain.framework.autoconfigure.cache.properties.CacheProperties;
import com.schbrain.framework.autoconfigure.cache.provider.CacheProvider;
import com.schbrain.framework.autoconfigure.cache.provider.CacheProviderDelegate;
import com.schbrain.framework.autoconfigure.cache.provider.redis.SchbrainRedisCacheConfiguration;
import com.schbrain.framework.autoconfigure.cache.provider.redis.RedisCacheConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
......@@ -18,15 +18,14 @@ import org.springframework.core.env.Environment;
* @author zhuyf
* @since 2022/7/25
*/
@Import(RedisCacheConfiguration.class)
@AutoConfiguration(after = RedisAutoConfiguration.class)
@EnableConfigurationProperties(CacheProperties.class)
@Import(SchbrainRedisCacheConfiguration.class)
public class SchbrainCacheAutoConfiguration {
public class CacheAutoConfiguration {
@Bean
@ConditionalOnBean(CacheProvider.class)
public CacheProviderDelegate cacheServiceDelegate(CacheProvider cacheProvider, CacheProperties cacheProperties,
Environment environment) {
public CacheProvider cacheProvider(CacheProvider cacheProvider, CacheProperties cacheProperties, Environment environment) {
CacheProviderDelegate delegate = new CacheProviderDelegate(cacheProperties, cacheProvider, environment);
CacheUtils.setCacheProvider(delegate);
return delegate;
......
package com.schbrain.framework.autoconfigure.cache.properties;
import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
......@@ -8,8 +10,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
* @since 2022/7/26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ConfigurationProperties(prefix = "schbrain.cache")
public class CacheProperties {
public class CacheProperties extends ConfigurableProperties {
/**
* cache prefix
......@@ -24,4 +27,9 @@ public class CacheProperties {
*/
private boolean appendPrefix = true;
@Override
public String getDefaultNamespace() {
return "cache-common";
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.cache.provider.redis;
import com.schbrain.framework.autoconfigure.cache.provider.CacheProvider;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
......@@ -13,13 +15,14 @@ import org.springframework.data.redis.core.StringRedisTemplate;
* @since 2022/8/7
*/
@ConditionalOnClass(RedisConnectionFactory.class)
public class SchbrainRedisCacheConfiguration {
@EnableConfigurationProperties(RedisProperties.class)
public class RedisCacheConfiguration {
@Bean
@ConditionalOnBean(RedisConnectionFactory.class)
@ConditionalOnMissingBean(RedisCacheProvider.class)
public CacheProvider schbrainRedisCacheProvider(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory);
public CacheProvider redisCacheProvider(RedisConnectionFactory redisConnectionFactory, ObjectProvider<StringRedisTemplate> redisTemplate) {
StringRedisTemplate stringRedisTemplate = redisTemplate.getIfAvailable(() -> new StringRedisTemplate(redisConnectionFactory));
return new RedisCacheProvider(stringRedisTemplate);
}
......
package com.schbrain.framework.autoconfigure.cache.provider.redis;
import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author liaozan
* @since 2023-04-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties extends ConfigurableProperties {
@Override
public String getDefaultNamespace() {
return "redis-common";
}
}
\ No newline at end of file
......@@ -4,6 +4,11 @@
"name": "schbrain.cache",
"type": "com.schbrain.framework.autoconfigure.cache.properties.CacheProperties",
"sourceType": "com.schbrain.framework.autoconfigure.cache.properties.CacheProperties"
},
{
"name": "spring.redis",
"type": "com.schbrain.framework.autoconfigure.cache.provider.redis.RedisProperties",
"sourceType": "com.schbrain.framework.autoconfigure.cache.provider.redis.RedisProperties"
}
],
"properties": [
......
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.cache.properties.CacheProperties,\
com.schbrain.framework.autoconfigure.cache.provider.redis.RedisProperties
\ No newline at end of file
com.schbrain.framework.autoconfigure.cache.SchbrainCacheAutoConfiguration
\ No newline at end of file
com.schbrain.framework.autoconfigure.cache.CacheAutoConfiguration
\ No newline at end of file
package com.schbrain.framework.autoconfigure.dubbo.listener;
import com.alibaba.fastjson2.JSONFactory;
import com.google.common.collect.Maps;
import com.schbrain.common.util.ApplicationName;
import com.schbrain.framework.autoconfigure.apollo.listener.PropertiesPreparedEvent;
import com.schbrain.framework.autoconfigure.apollo.listener.PropertiesPreparedEventListenerAdapter;
import com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.spring.ConfigCenterBean;
import org.apache.dubbo.config.spring.util.EnvironmentUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.Map;
import java.util.SortedMap;
import static org.apache.dubbo.config.ConfigKeys.DUBBO_SCAN_BASE_PACKAGES;
/**
* @author liaozan
* @since 2023-04-28
*/
public class DubboPropertiesPreparedEventListener extends PropertiesPreparedEventListenerAdapter<DubboProperties> {
public static final String DUBBO_APPLICATION_NAME = "dubbo.application.name";
@Override
protected void onPropertiesPrepared(PropertiesPreparedEvent event, DubboProperties properties) {
ConfigurableEnvironment environment = event.getEnvironment();
Map<String, String> requiredProperties = collectRequiredProperties(environment, event.getApplication());
event.getPropertySource().addProperties(requiredProperties);
injectDubboProperties(environment);
}
private void injectDubboProperties(ConfigurableEnvironment environment) {
JSONFactory.setUseJacksonAnnotation(false);
SortedMap<String, String> dubboProperties = EnvironmentUtils.filterDubboProperties(environment);
ConfigCenterBean configCenterBean = new ConfigCenterBean();
configCenterBean.setExternalConfig(dubboProperties);
DubboBootstrap.getInstance().configCenter(configCenterBean);
}
private Map<String, String> collectRequiredProperties(ConfigurableEnvironment environment, SpringApplication application) {
Map<String, String> dubboRequiredProperties = Maps.newLinkedHashMapWithExpectedSize(2);
dubboRequiredProperties.put(DUBBO_SCAN_BASE_PACKAGES, getBasePackage(application));
dubboRequiredProperties.put(DUBBO_APPLICATION_NAME, ApplicationName.get(environment));
return dubboRequiredProperties;
}
private String getBasePackage(SpringApplication application) {
return application.getMainApplicationClass().getPackage().getName();
}
}
\ No newline at end of file
......@@ -3,12 +3,7 @@ package com.schbrain.framework.autoconfigure.dubbo.properties;
import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.dubbo.config.spring.util.EnvironmentUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* used to fetch dubbo.* config from remote
......@@ -21,27 +16,9 @@ import java.util.Map;
@ConfigurationProperties(prefix = "dubbo")
public class DubboProperties extends ConfigurableProperties {
private Map<String, String> externalConfigurations;
@Override
public String getDefaultNamespace() {
return "dubbo-common";
}
@Override
@SuppressWarnings("unchecked")
public DubboProperties bindOrCreate(ConfigurableEnvironment environment, boolean afterMerge) {
DubboProperties dubboProperties = super.bindOrCreate(environment, afterMerge);
if (afterMerge) {
Map<String, String> externalConfigurations = new LinkedHashMap<>(EnvironmentUtils.filterDubboProperties(environment));
Map<String, String> configuredProperties = dubboProperties.getExternalConfigurations();
if (configuredProperties == null) {
configuredProperties = new LinkedHashMap<>();
}
externalConfigurations.putAll(configuredProperties);
dubboProperties.setExternalConfigurations(externalConfigurations);
}
return dubboProperties;
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.dubbo.properties;
import com.alibaba.fastjson2.JSONFactory;
import com.schbrain.common.exception.BaseException;
import com.schbrain.common.util.ApplicationName;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.spring.ConfigCenterBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.apache.dubbo.config.ConfigKeys.DUBBO_SCAN_BASE_PACKAGES;
/**
* @author liaozan
* @since 2021/10/10
*/
public class DubboPropertiesPreparer implements EnvironmentPostProcessor, Ordered {
public static final String DUBBO_APPLICATION_NAME = "dubbo.application.name";
public static final Integer DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE;
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
DubboProperties dubboProperties = ConfigUtils.loadConfig(environment, DubboProperties.class);
addAdditionalProperties(environment, application, dubboProperties);
setUpConfigCenter(dubboProperties);
JSONFactory.setUseJacksonAnnotation(false);
}
@Override
public int getOrder() {
return DEFAULT_ORDER;
}
private void setUpConfigCenter(DubboProperties dubboProperties) {
ConfigCenterBean configCenterConfig = buildConfigCenter(dubboProperties);
DubboBootstrap.getInstance().configCenter(configCenterConfig);
}
private ConfigCenterBean buildConfigCenter(DubboProperties dubboProperties) {
ConfigCenterBean configCenter = new ConfigCenterBean();
configCenter.setExternalConfig(dubboProperties.getExternalConfigurations());
return configCenter;
}
private void addAdditionalProperties(ConfigurableEnvironment environment, SpringApplication application, DubboProperties dubboProperties) {
Map<String, String> configurations = dubboProperties.getExternalConfigurations();
configurations.put(DUBBO_SCAN_BASE_PACKAGES, getBasePackage(application));
if (!configurations.containsKey(DUBBO_APPLICATION_NAME)) {
configurations.put(DUBBO_APPLICATION_NAME, ApplicationName.get(environment));
}
Map<String, Object> properties = new LinkedHashMap<>(dubboProperties.getExternalConfigurations());
ConfigUtils.addToEnvironment(environment, dubboProperties.getName(), properties);
}
private String getBasePackage(SpringApplication application) {
return application.getAllSources()
.stream()
.filter(Class.class::isInstance)
.map(source -> (Class<?>) source)
.map(Class::getPackage)
.map(Package::getName)
.findFirst()
.orElseThrow(() -> new BaseException("should never go here"));
}
}
\ No newline at end of file
......@@ -6,27 +6,6 @@
"sourceType": "com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties"
}
],
"properties": [
{
"name": "dubbo.external-configurations",
"type": "java.util.Map<java.lang.String,java.lang.String>",
"sourceType": "com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties"
},
{
"name": "dubbo.name",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties"
},
{
"name": "dubbo.namespace",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties"
},
{
"name": "dubbo.prefix",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties"
}
],
"properties": [],
"hints": []
}
\ No newline at end of file
org.springframework.boot.env.EnvironmentPostProcessor=com.schbrain.framework.autoconfigure.dubbo.properties.DubboPropertiesPreparer
\ No newline at end of file
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.dubbo.properties.DubboProperties
org.springframework.context.ApplicationListener=\
com.schbrain.framework.autoconfigure.dubbo.listener.DubboPropertiesPreparedEventListener
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.schbrain.framework</groupId>
<artifactId>starters</artifactId>
<version>${revision}</version>
</parent>
<artifactId>elasticsearch-spring-boot-starter</artifactId>
<dependencies>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>apollo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.schbrain.framework.autoconfigure.elasticsearch;
import com.schbrain.framework.autoconfigure.elasticsearch.properties.ElasticsearchProperties;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* @author liaozan
* @since 2023-04-29
*/
@AutoConfiguration
@EnableConfigurationProperties(ElasticsearchProperties.class)
public class ElasticsearchAutoConfiguration {
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.elasticsearch.properties;
import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author liaozan
* @since 2023-04-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ConfigurationProperties(prefix = "spring.elasticsearch")
public class ElasticsearchProperties extends ConfigurableProperties {
@Override
public String getDefaultNamespace() {
return "elasticsearch-common";
}
}
\ No newline at end of file
{
"groups": [
{
"name": "spring.elasticsearch",
"type": "com.schbrain.framework.autoconfigure.elasticsearch.properties.ElasticsearchProperties",
"sourceType": "com.schbrain.framework.autoconfigure.elasticsearch.properties.ElasticsearchProperties"
}
],
"properties": [],
"hints": []
}
\ No newline at end of file
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.elasticsearch.properties.ElasticsearchProperties
\ No newline at end of file
com.schbrain.framework.autoconfigure.elasticsearch.ElasticsearchAutoConfiguration
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.schbrain.framework</groupId>
<artifactId>starters</artifactId>
<version>${revision}</version>
</parent>
<artifactId>kafka-spring-boot-starter</artifactId>
<dependencies>
<dependency>
<groupId>com.schbrain.framework</groupId>
<artifactId>apollo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.schbrain.framework.autoconfigure.kafka;
import com.schbrain.framework.autoconfigure.kafka.properties.KafkaProperties;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* @author liaozan
* @since 2023-04-29
*/
@AutoConfiguration
@EnableConfigurationProperties(KafkaProperties.class)
public class KafkaAutoConfiguration {
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.kafka.properties;
import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author liaozan
* @since 2023-04-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ConfigurationProperties(prefix = "spring.kafka")
public class KafkaProperties extends ConfigurableProperties {
@Override
public String getDefaultNamespace() {
return "kafka-common";
}
}
\ No newline at end of file
{
"groups": [
{
"name": "spring.kafka",
"type": "com.schbrain.framework.autoconfigure.kafka.properties.KafkaProperties",
"sourceType": "com.schbrain.framework.autoconfigure.kafka.properties.KafkaProperties"
}
],
"properties": [],
"hints": []
}
\ No newline at end of file
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.kafka.properties.KafkaProperties
\ No newline at end of file
com.schbrain.framework.autoconfigure.kafka.KafkaAutoConfiguration
\ No newline at end of file
package com.schbrain.framework.autoconfigure.logger;
import com.schbrain.framework.autoconfigure.logger.apollo.DynamicLoggerConfiguration;
import com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties;
import com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
......@@ -15,7 +15,7 @@ import org.springframework.core.Ordered;
@AutoConfiguration
@Import(DynamicLoggerConfiguration.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@EnableConfigurationProperties(LoggingFileProperties.class)
@EnableConfigurationProperties(LoggerProperties.class)
public class LoggerAutoConfiguration {
}
\ No newline at end of file
......@@ -9,10 +9,8 @@ import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import cn.hutool.json.JSONObject;
import com.schbrain.common.util.*;
import com.schbrain.common.util.InetUtils.HostInfo;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import com.schbrain.framework.autoconfigure.logger.logstash.SchbrainLogstashEncoder;
import com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties;
import lombok.Setter;
import com.schbrain.framework.autoconfigure.logger.logstash.EnhancedLogstashEncoder;
import com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties;
import lombok.extern.slf4j.Slf4j;
import net.logstash.logback.appender.LogstashTcpSocketAppender;
import net.logstash.logback.encoder.LogstashEncoder;
......@@ -20,8 +18,6 @@ import net.logstash.logback.fieldnames.ShortenedFieldNames;
import org.apache.commons.collections4.IteratorUtils;
import org.slf4j.LoggerFactory;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
......@@ -37,25 +33,23 @@ import java.util.List;
* @since 2021/12/11
*/
@Slf4j
@Setter
public class JsonLoggerInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
/**
* 暴露 set 方法以便单独启动日志服务时进行配置
*/
private ConfigurableEnvironment environment;
private LoggingFileProperties loggingFileProperties;
private String applicationName;
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
this.environment = applicationContext.getEnvironment();
this.loggingFileProperties = ConfigUtils.loadConfig(environment, LoggingFileProperties.class);
public class LoggerConfigurationInitializer {
private final ConfigurableEnvironment environment;
private final LoggerProperties properties;
private final String applicationName;
public LoggerConfigurationInitializer(ConfigurableEnvironment environment, LoggerProperties properties) {
this.environment = environment;
this.properties = properties;
this.applicationName = ApplicationName.get(environment);
this.init();
}
public void init() {
if (properties == null) {
return;
}
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
for (Logger logger : context.getLoggerList()) {
registerAppender(logger, context);
......@@ -68,18 +62,18 @@ public class JsonLoggerInitializer implements ApplicationContextInitializer<Conf
return;
}
if (loggingFileProperties.isEnableJsonFileOutput()) {
if (properties.isEnableJsonFileOutput()) {
Appender<ILoggingEvent> appender = buildFileAppender(context);
logger.addAppender(appender);
}
if (loggingFileProperties.isEnableJsonConsoleOutput()) {
if (properties.isEnableJsonConsoleOutput()) {
Appender<ILoggingEvent> appender = buildConsoleAppender(context);
logger.addAppender(appender);
}
if (loggingFileProperties.isEnableJsonLogWriteToLogstash() || EnvUtils.runningOnCloudPlatform(environment)) {
if (!StringUtils.hasText(loggingFileProperties.getLogstashAddress())) {
if (properties.isEnableJsonLogWriteToLogstash() || EnvUtils.runningOnCloudPlatform(environment)) {
if (!StringUtils.hasText(properties.getLogstashAddress())) {
log.warn("logstash address is unset, will NOT write log to logstash");
return;
}
......@@ -91,7 +85,7 @@ public class JsonLoggerInitializer implements ApplicationContextInitializer<Conf
private Appender<ILoggingEvent> buildLogstashAppender(LoggerContext context) {
LogstashTcpSocketAppender appender = new LogstashTcpSocketAppender();
appender.setContext(context);
appender.addDestination(loggingFileProperties.getLogstashAddress());
appender.addDestination(properties.getLogstashAddress());
appender.setEncoder(createJsonEncoder(context));
appender.start();
return appender;
......@@ -110,7 +104,7 @@ public class JsonLoggerInitializer implements ApplicationContextInitializer<Conf
}
private LogstashEncoder createJsonEncoder(LoggerContext loggerContext) {
LogstashEncoder logstashEncoder = new SchbrainLogstashEncoder();
LogstashEncoder logstashEncoder = new EnhancedLogstashEncoder();
logstashEncoder.setContext(loggerContext);
logstashEncoder.setFieldNames(new ShortenedFieldNames());
logstashEncoder.setShortenedLoggerNameLength(40);
......@@ -139,12 +133,12 @@ public class JsonLoggerInitializer implements ApplicationContextInitializer<Conf
}
private String getPathLocation(String path) {
return Paths.get(loggingFileProperties.getLogPath(), path).toString();
return Paths.get(properties.getLogPath(), path).toString();
}
private TimeBasedRollingPolicy<ILoggingEvent> createRollingPolicy(Context context, FileAppender<ILoggingEvent> appender) {
TimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new TimeBasedRollingPolicy<>();
rollingPolicy.setMaxHistory(loggingFileProperties.getMaxHistory());
rollingPolicy.setMaxHistory(properties.getMaxHistory());
rollingPolicy.setFileNamePattern(getPathLocation("json/json-%d{yyyy-MM-dd}.log"));
rollingPolicy.setContext(context);
rollingPolicy.setParent(appender);
......
package com.schbrain.framework.autoconfigure.logger.apollo;
import com.ctrip.framework.apollo.*;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import com.schbrain.framework.autoconfigure.logger.apollo.listener.LoggingConfigFileChangeListener;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.schbrain.framework.autoconfigure.logger.apollo.listener.LoggingLevelChangeListener;
import com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties;
import com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
/**
......@@ -19,47 +15,14 @@ import org.springframework.util.StringUtils;
* @since 2021/11/19
**/
@Slf4j
@EnableConfigurationProperties(LoggingNamespaceProperties.class)
public class DynamicLoggerConfiguration {
private final ConfigurableEnvironment environment;
private final LoggingSystem loggingSystem;
private final LoggingNamespaceProperties loggerProperties;
public DynamicLoggerConfiguration(ConfigurableEnvironment environment, LoggingSystem loggingSystem,
LoggingNamespaceProperties loggerProperties) {
this.environment = environment;
this.loggingSystem = loggingSystem;
this.loggerProperties = loggerProperties;
this.init();
}
private void init() {
if (ConfigUtils.isApolloDisabled()) {
return;
}
listenToLoggingLevelChange();
listenToLoggingConfigFileChange();
}
private void listenToLoggingConfigFileChange() {
String loggerConfigFileNamespace = loggerProperties.getLoggerConfigFile();
if (!StringUtils.hasText(loggerConfigFileNamespace)) {
log.debug("logger config file reload is disabled");
return;
}
log.debug("init logger config file listener, config file namespace: {}", loggerConfigFileNamespace);
ConfigFile loggingConfiguration = ConfigService.getConfigFile(loggerConfigFileNamespace, ConfigFileFormat.XML);
if (!loggingConfiguration.hasContent()) {
return;
}
loggingConfiguration.addChangeListener(new LoggingConfigFileChangeListener(loggingSystem, environment, loggerConfigFileNamespace));
public DynamicLoggerConfiguration(LoggingSystem loggingSystem, LoggerProperties loggerProperties) {
this.listenToLoggingLevelChange(loggingSystem, loggerProperties);
}
private void listenToLoggingLevelChange() {
String loggerNamespace = loggerProperties.getLogger();
private void listenToLoggingLevelChange(LoggingSystem loggingSystem, LoggerProperties loggerProperties) {
String loggerNamespace = loggerProperties.getDefaultNamespace();
if (!StringUtils.hasText(loggerNamespace)) {
log.debug("logger level reload is disabled");
return;
......
package com.schbrain.framework.autoconfigure.logger.apollo.listener;
import cn.hutool.extra.spring.SpringUtil;
import com.ctrip.framework.apollo.ConfigFileChangeListener;
import com.ctrip.framework.apollo.model.ConfigFileChangeEvent;
import com.schbrain.framework.autoconfigure.logger.JsonLoggerInitializer;
import com.schbrain.framework.autoconfigure.logger.util.LoggerUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.logging.*;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* @author liaozan
* @since 2021/11/8
*/
@Slf4j
public class LoggingConfigFileChangeListener implements ConfigFileChangeListener {
private final LoggingSystem loggingSystem;
private final ConfigurableEnvironment environment;
private final String loggerFileName;
public LoggingConfigFileChangeListener(LoggingSystem loggingSystem, ConfigurableEnvironment environment, String loggerFileName) {
this.loggingSystem = loggingSystem;
this.environment = environment;
this.loggerFileName = loggerFileName;
}
@Override
public void onChange(ConfigFileChangeEvent changeEvent) {
String content = changeEvent.getNewValue();
if (!StringUtils.hasText(content)) {
log.warn("Empty logging configuration, reInitialize loggingSystem is disabled");
return;
}
String configurationLocation = LoggerUtils.storeConfiguration(loggerFileName, content);
if (configurationLocation == null) {
return;
}
reinitialize(configurationLocation);
log.debug("ReInitialize loggingSystem, configFile location: {}", configurationLocation);
}
private void reinitialize(String configLocation) {
List<LoggerConfiguration> configurations = loggingSystem.getLoggerConfigurations();
loggingSystem.cleanUp();
loggingSystem.initialize(new LoggingInitializationContext(environment), configLocation, null);
configurations.forEach(configuration -> loggingSystem.setLogLevel(configuration.getName(), configuration.getConfiguredLevel()));
// reInitialize json logger
new JsonLoggerInitializer().initialize(SpringUtil.getBean(ConfigurableApplicationContext.class));
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.logger.listener;
import cn.hutool.system.SystemUtil;
import com.ctrip.framework.apollo.ConfigFile;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.google.common.collect.Maps;
import com.schbrain.common.util.InetUtils;
import com.schbrain.common.util.InetUtils.HostInfo;
import com.schbrain.framework.autoconfigure.apollo.listener.PropertiesPreparedEvent;
import com.schbrain.framework.autoconfigure.apollo.listener.PropertiesPreparedEventListenerAdapter;
import com.schbrain.framework.autoconfigure.logger.LoggerConfigurationInitializer;
import com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.nio.file.*;
import java.util.Map;
import static org.springframework.boot.context.logging.LoggingApplicationListener.CONFIG_PROPERTY;
/**
* @author liaozan
* @since 2023-04-28
*/
@Slf4j
public class LoggerPropertiesPreparedEventListener extends PropertiesPreparedEventListenerAdapter<LoggerProperties> {
@Override
protected void onPropertiesPrepared(PropertiesPreparedEvent event, LoggerProperties properties) {
ConfigurableEnvironment environment = event.getEnvironment();
Map<String, String> hostInfoProperties = buildHostInfoProperties();
event.getPropertySource().addProperties(hostInfoProperties);
configLoggingFileLocation(environment);
new LoggerConfigurationInitializer(environment, properties).init();
}
private Map<String, String> buildHostInfoProperties() {
HostInfo hostInfo = InetUtils.findFirstNonLoopBackHostInfo();
Map<String, String> properties = Maps.newHashMapWithExpectedSize(2);
properties.put("application.hostname", hostInfo.getHostname());
properties.put("application.ipAddress", hostInfo.getIpAddress());
return properties;
}
/**
* Add {@link org.springframework.boot.context.logging.LoggingApplicationListener#CONFIG_PROPERTY} property to SystemProperty
*
* @see org.springframework.boot.context.logging.LoggingApplicationListener#initializeSystem(ConfigurableEnvironment, org.springframework.boot.logging.LoggingSystem, org.springframework.boot.logging.LogFile)
*/
@SuppressWarnings("JavadocReference")
private void configLoggingFileLocation(ConfigurableEnvironment environment) {
if (environment.containsProperty(CONFIG_PROPERTY)) {
return;
}
ConfigFile loggingConfiguration = ConfigService.getConfigFile("logback-spring", ConfigFileFormat.XML);
String content = loggingConfiguration.getContent();
if (!StringUtils.hasText(content)) {
log.warn("empty logging configuration, reinitialize loggingSystem is disabled");
return;
}
String loggerConfigurationLocation = null;
String tempDir = SystemUtil.getUserInfo().getTempDir();
Path storeLocation = Paths.get(tempDir, "logback-spring.xml");
try {
loggerConfigurationLocation = Files.writeString(storeLocation, content).toString();
} catch (IOException e) {
log.warn("failed to write logging file, will not behave as expected", e);
}
if (loggerConfigurationLocation == null) {
return;
}
System.setProperty(CONFIG_PROPERTY, loggerConfigurationLocation);
log.debug(String.format("%s is set to %s", CONFIG_PROPERTY, loggerConfigurationLocation));
}
}
\ No newline at end of file
......@@ -8,11 +8,11 @@ import net.logstash.logback.encoder.LogstashEncoder;
* @author liaozan
* @since 2022/1/4
*/
public class SchbrainLogstashEncoder extends LogstashEncoder {
public class EnhancedLogstashEncoder extends LogstashEncoder {
@Override
protected AbstractCompositeJsonFormatter<ILoggingEvent> createFormatter() {
return new SchbrainLogstashFormatter(this);
return new EnhancedLogstashFormatter(this);
}
}
}
\ No newline at end of file
......@@ -15,9 +15,9 @@ import java.util.List;
* @author liaozan
* @since 2022/1/4
*/
public class SchbrainLogstashFormatter extends LogstashFormatter {
public class EnhancedLogstashFormatter extends LogstashFormatter {
public SchbrainLogstashFormatter(ContextAware declaredOrigin) {
public EnhancedLogstashFormatter(ContextAware declaredOrigin) {
super(declaredOrigin);
configureProviders();
}
......@@ -63,4 +63,4 @@ public class SchbrainLogstashFormatter extends LogstashFormatter {
return excludeProviders;
}
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.PriorityOrdered;
import java.time.Duration;
......@@ -14,7 +15,7 @@ import java.time.Duration;
@Data
@EqualsAndHashCode(callSuper = true)
@ConfigurationProperties(prefix = "schbrain.logging.file")
public class LoggingFileProperties extends ConfigurableProperties {
public class LoggerProperties extends ConfigurableProperties implements PriorityOrdered {
public static final String DEFAULT_LOG_PATH = "/data/logs";
......@@ -30,4 +31,14 @@ public class LoggingFileProperties extends ConfigurableProperties {
private int maxHistory = (int) Duration.ofDays(30).toDays();
@Override
public String getDefaultNamespace() {
return "logger-common";
}
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.logger.properties;
import com.google.common.collect.Maps;
import com.schbrain.common.util.InetUtils;
import com.schbrain.common.util.InetUtils.HostInfo;
import com.schbrain.framework.autoconfigure.apollo.properties.ApolloPropertiesPreparer;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import com.schbrain.framework.autoconfigure.logger.util.LoggerUtils;
import com.schbrain.framework.support.spring.EnvironmentPostProcessorAdapter;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.logging.LoggingApplicationListener;
import org.springframework.boot.logging.*;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.Map;
import static com.schbrain.framework.autoconfigure.logger.util.LoggerUtils.getLoggerConfigurationLocation;
import static org.springframework.boot.context.logging.LoggingApplicationListener.CONFIG_PROPERTY;
/**
* @author liaozan
* @since 2021/11/19
*/
public class LoggerPropertiesPreparer extends EnvironmentPostProcessorAdapter implements Ordered {
public LoggerPropertiesPreparer(DeferredLogFactory factory, ConfigurableBootstrapContext bootstrapContext) {
super(factory, bootstrapContext);
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
LoggerUtils.setLogFactory(getDeferredLogFactory());
bindLoggingProperties(environment);
bindHostInfoProperty(environment);
earlyLoadLoggingConfig(environment);
}
@Override
public int getOrder() {
// Configure after the apollo property is initialize
return ApolloPropertiesPreparer.ORDER + 1;
}
@Override
public void onBootstrapContextClosed(ConfigurableApplicationContext applicationContext) {
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
if (!beanFactory.containsSingleton(HostInfo.NAME)) {
HostInfo hostInfo = InetUtils.findFirstNonLoopBackHostInfo();
beanFactory.registerSingleton(HostInfo.NAME, hostInfo);
}
}
private void bindHostInfoProperty(ConfigurableEnvironment environment) {
HostInfo hostInfo = InetUtils.findFirstNonLoopBackHostInfo();
Map<String, Object> source = Maps.newHashMapWithExpectedSize(2);
source.put("application.hostname", hostInfo.getHostname());
source.put("application.ipAddress", hostInfo.getIpAddress());
ConfigUtils.addToEnvironment(environment, HostInfo.NAME, source);
}
/**
* @see LoggingApplicationListener#setLogLevels(LoggingSystem, ConfigurableEnvironment)
*/
@SuppressWarnings("JavadocReference")
private void earlyLoadLoggingConfig(ConfigurableEnvironment environment) {
LoggingNamespaceProperties properties = ConfigUtils.loadConfig(environment, LoggingNamespaceProperties.class);
// load logging level properties
Map<String, Object> loggingLevelProperties = ConfigUtils.loadConfig(properties.getLogger());
ConfigUtils.addToEnvironment(environment, "loggingLevelProperties", loggingLevelProperties);
// load logging file properties
ConfigUtils.loadConfig(environment, LoggingFileProperties.class);
}
/**
* Add {@link LoggingApplicationListener#CONFIG_PROPERTY} property to SystemProperty
*
* @see LoggingApplicationListener#initializeSystem(ConfigurableEnvironment, LoggingSystem, LogFile)
*/
@SuppressWarnings("JavadocReference")
private void bindLoggingProperties(ConfigurableEnvironment environment) {
if (environment.containsProperty(CONFIG_PROPERTY)) {
return;
}
String loggerConfigurationLocation = getLoggerConfigurationLocation(environment);
if (loggerConfigurationLocation == null) {
return;
}
System.setProperty(CONFIG_PROPERTY, loggerConfigurationLocation);
getLog().debug(String.format("%s is set to %s", CONFIG_PROPERTY, loggerConfigurationLocation));
}
}
\ No newline at end of file
package com.schbrain.framework.autoconfigure.logger.util;
import cn.hutool.system.SystemUtil;
import com.ctrip.framework.apollo.ConfigFile;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties;
import org.apache.commons.logging.Log;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
/**
* @author liaozan
* @since 2021/11/15
*/
public class LoggerUtils {
private static Log LOGGER;
public static void setLogFactory(DeferredLogFactory deferredLog) {
LOGGER = deferredLog.getLog(LoggerUtils.class);
}
@Nullable
public static String getLoggerConfigurationLocation(ConfigurableEnvironment environment) {
if (ConfigUtils.isApolloDisabled()) {
return null;
}
LoggingNamespaceProperties properties = ConfigUtils.loadConfig(environment, LoggingNamespaceProperties.class);
String namespace = properties.getLoggerConfigFile();
ConfigFile loggingConfiguration = ConfigService.getConfigFile(namespace, ConfigFileFormat.XML);
String content = loggingConfiguration.getContent();
if (!StringUtils.hasText(content)) {
LOGGER.warn("empty logging configuration, reinitialize loggingSystem is disabled");
return null;
}
return storeConfiguration(namespace, content);
}
@Nullable
public static String storeConfiguration(String fileName, String content) {
String tempDir = SystemUtil.getUserInfo().getTempDir();
Path storeLocation = Paths.get(tempDir, fileName + ".xml");
try {
return Files.write(storeLocation, content.getBytes(StandardCharsets.UTF_8)).toString();
} catch (IOException e) {
LOGGER.warn("failed to write logging file, will not behave as expected", e);
return null;
}
}
}
\ No newline at end of file
......@@ -2,92 +2,45 @@
"groups": [
{
"name": "schbrain.logging.file",
"type": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties"
},
{
"name": "schbrain.logging.namespace",
"type": "com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties"
"type": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties"
}
],
"properties": [
{
"name": "schbrain.logging.file.enable-json-console-output",
"type": "java.lang.Boolean",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties",
"defaultValue": false
},
{
"name": "schbrain.logging.file.enable-json-file-output",
"type": "java.lang.Boolean",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties",
"defaultValue": false
},
{
"name": "schbrain.logging.file.enable-json-log-write-to-logstash",
"type": "java.lang.Boolean",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties",
"defaultValue": false
},
{
"name": "schbrain.logging.file.log-path",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties",
"defaultValue": "\/data\/logs"
},
{
"name": "schbrain.logging.file.logstash-address",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties"
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties"
},
{
"name": "schbrain.logging.file.max-history",
"type": "java.lang.Integer",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties",
"defaultValue": 0
},
{
"name": "schbrain.logging.file.name",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties"
},
{
"name": "schbrain.logging.file.namespace",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties"
},
{
"name": "schbrain.logging.file.prefix",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties"
},
{
"name": "schbrain.logging.namespace.logger",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties",
"defaultValue": "logger-common"
},
{
"name": "schbrain.logging.namespace.logger-config-file",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties",
"defaultValue": "logback-spring"
},
{
"name": "schbrain.logging.namespace.name",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties"
},
{
"name": "schbrain.logging.namespace.namespace",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties"
},
{
"name": "schbrain.logging.namespace.prefix",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.logger.properties.LoggingNamespaceProperties"
}
],
"hints": []
......
org.springframework.context.ApplicationContextInitializer=\
com.schbrain.framework.autoconfigure.logger.JsonLoggerInitializer,\
com.schbrain.framework.autoconfigure.logger.logback.LogbackTraceIdConfiguration
org.springframework.boot.env.EnvironmentPostProcessor=com.schbrain.framework.autoconfigure.logger.properties.LoggerPropertiesPreparer
\ No newline at end of file
org.springframework.context.ApplicationListener=\
com.schbrain.framework.autoconfigure.logger.listener.LoggerPropertiesPreparedEventListener
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties
\ No newline at end of file
......@@ -14,8 +14,7 @@ import com.schbrain.framework.autoconfigure.mybatis.datasource.customizer.DataSo
import com.schbrain.framework.autoconfigure.mybatis.datasource.customizer.DefaultDataSourceCustomizer;
import com.schbrain.framework.autoconfigure.mybatis.datasource.extractor.*;
import com.schbrain.framework.autoconfigure.mybatis.listener.TableConstraintCheckerBean;
import com.schbrain.framework.autoconfigure.mybatis.properties.DataSourceConnectionProperties;
import com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties;
import com.schbrain.framework.autoconfigure.mybatis.properties.*;
import com.schbrain.framework.autoconfigure.mybatis.sql.injector.DefaultMethodSqlInjector;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
......@@ -33,7 +32,7 @@ import java.util.List;
* @since 2021/10/14
*/
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class)
@EnableConfigurationProperties({MybatisProperties.class, DataSourceConnectionProperties.class})
@EnableConfigurationProperties({DataSourceProperties.class, MybatisProperties.class, DataSourceConnectionProperties.class})
@Import({HikariDataSourcePropertiesExtractor.class, DruidDataSourcePropertiesExtractor.class})
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class MybatisAutoConfiguration {
......
package com.schbrain.framework.autoconfigure.logger.properties;
package com.schbrain.framework.autoconfigure.mybatis.properties;
import com.schbrain.common.util.support.ConfigurableProperties;
import lombok.Data;
......@@ -7,15 +7,16 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author liaozan
* @since 2021/11/24
* @since 2023-04-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ConfigurationProperties(prefix = "schbrain.logging.namespace")
public class LoggingNamespaceProperties extends ConfigurableProperties {
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties extends ConfigurableProperties {
private String logger = "logger-common";
private String loggerConfigFile = "logback-spring";
@Override
public String getDefaultNamespace() {
return "jdbc-common";
}
}
\ No newline at end of file
......@@ -9,6 +9,11 @@
"name": "schbrain.mybatis",
"type": "com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties",
"sourceType": "com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties"
},
{
"name": "spring.datasource",
"type": "com.schbrain.framework.autoconfigure.mybatis.properties.DataSourceProperties",
"sourceType": "com.schbrain.framework.autoconfigure.mybatis.properties.DataSourceProperties"
}
],
"properties": [
......@@ -92,21 +97,6 @@
"description": "是否开启表约束检查",
"sourceType": "com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties",
"defaultValue": true
},
{
"name": "schbrain.mybatis.name",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties"
},
{
"name": "schbrain.mybatis.namespace",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties"
},
{
"name": "schbrain.mybatis.prefix",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties"
}
],
"hints": []
......
org.springframework.boot.diagnostics.FailureAnalyzer=com.schbrain.framework.autoconfigure.mybatis.constraint.TableConstraintCheckFailureAnalyzer
\ No newline at end of file
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.schbrain.framework.autoconfigure.mybatis.constraint.TableConstraintCheckFailureAnalyzer
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.mybatis.properties.MybatisProperties,\
com.schbrain.framework.autoconfigure.mybatis.properties.DataSourceProperties
\ No newline at end of file
package com.schbrain.framework.autoconfigure.oss;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import com.schbrain.framework.autoconfigure.oss.properties.OssProperties;
import com.schbrain.framework.autoconfigure.oss.util.OssUtils;
import org.springframework.boot.autoconfigure.AutoConfiguration;
......@@ -16,13 +15,8 @@ import org.springframework.core.env.ConfigurableEnvironment;
@EnableConfigurationProperties(OssProperties.class)
public class OssAutoConfiguration {
public OssAutoConfiguration(ConfigurableApplicationContext applicationContext) {
initialize(applicationContext);
}
private void initialize(ConfigurableApplicationContext applicationContext) {
public OssAutoConfiguration(ConfigurableApplicationContext applicationContext, OssProperties ossProperties) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
OssProperties ossProperties = ConfigUtils.loadConfig(environment, OssProperties.class);
OssUtils.initialize(environment, ossProperties);
}
......
......@@ -38,21 +38,6 @@
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.oss.properties.OssProperties"
},
{
"name": "schbrain.oss.name",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.oss.properties.OssProperties"
},
{
"name": "schbrain.oss.namespace",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.oss.properties.OssProperties"
},
{
"name": "schbrain.oss.prefix",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.oss.properties.OssProperties"
},
{
"name": "schbrain.oss.secret-access-key",
"type": "java.lang.String",
......
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.oss.properties.OssProperties
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
......@@ -19,6 +19,8 @@
<module>apollo-spring-boot-starter</module>
<module>cache-spring-boot-starter</module>
<module>dubbo-spring-boot-starter</module>
<module>elasticsearch-spring-boot-starter</module>
<module>kafka-spring-boot-starter</module>
<module>logger-spring-boot-starter</module>
<module>mybatis-spring-boot-starter</module>
<module>oss-spring-boot-starter</module>
......
package com.schbrain.framework.autoconfigure.xxl;
import com.schbrain.common.util.ApplicationName;
import com.schbrain.framework.autoconfigure.apollo.util.ConfigUtils;
import com.schbrain.framework.autoconfigure.logger.properties.LoggingFileProperties;
import com.schbrain.framework.autoconfigure.logger.properties.LoggerProperties;
import com.schbrain.framework.autoconfigure.xxl.condition.XxlJobShouldAvailableCondition;
import com.schbrain.framework.autoconfigure.xxl.properties.XxlJobProperties;
import com.xxl.job.core.executor.XxlJobExecutor;
......@@ -26,9 +25,9 @@ public class XxlJobAutoConfiguration {
@Bean
@ConditionalOnMissingBean(XxlJobExecutor.class)
public SchbrainXxlJobExecutor schbrainXxlJobSpringExecutor(ConfigurableEnvironment environment) {
XxlJobProperties xxlJobProperties = ConfigUtils.loadConfig(environment, XxlJobProperties.class);
LoggingFileProperties loggingProperties = ConfigUtils.loadConfig(environment, LoggingFileProperties.class);
public SchbrainXxlJobExecutor schbrainXxlJobSpringExecutor(ConfigurableEnvironment environment,
XxlJobProperties xxlJobProperties,
LoggerProperties loggingProperties) {
String applicationName = ApplicationName.get(environment);
SchbrainXxlJobExecutor executor = new SchbrainXxlJobExecutor();
executor.setAdminAddresses(xxlJobProperties.getAdminAddresses());
......
......@@ -28,27 +28,12 @@
"sourceType": "com.schbrain.framework.autoconfigure.xxl.properties.XxlJobProperties",
"defaultValue": 7
},
{
"name": "schbrain.xxl.name",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.xxl.properties.XxlJobProperties"
},
{
"name": "schbrain.xxl.namespace",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.xxl.properties.XxlJobProperties"
},
{
"name": "schbrain.xxl.port",
"type": "java.lang.Integer",
"sourceType": "com.schbrain.framework.autoconfigure.xxl.properties.XxlJobProperties",
"defaultValue": -1
},
{
"name": "schbrain.xxl.prefix",
"type": "java.lang.String",
"sourceType": "com.schbrain.framework.autoconfigure.xxl.properties.XxlJobProperties"
},
{
"name": "schbrain.xxl.register",
"type": "java.lang.Boolean",
......
com.schbrain.common.util.support.ConfigurableProperties=\
com.schbrain.framework.autoconfigure.xxl.properties.XxlJobProperties
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
......
package com.schbrain.framework.support.spring;
import cn.hutool.core.lang.Singleton;
import org.springframework.boot.BootstrapContextClosedEvent;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import java.util.ArrayList;
import java.util.List;
/**
* @author liaozan
* @since 2021/11/22
*/
public class BootstrapContextListenerComposite implements ApplicationListener<BootstrapContextClosedEvent> {
private final List<EnvironmentPostProcessorAdapter> adapters = new ArrayList<>();
public static BootstrapContextListenerComposite getInstance() {
return Singleton.get(BootstrapContextListenerComposite.class);
}
public void addListener(EnvironmentPostProcessorAdapter adapter) {
if (adapters.contains(adapter)) {
return;
}
adapters.add(adapter);
}
@Override
public void onApplicationEvent(BootstrapContextClosedEvent event) {
if (adapters.isEmpty()) {
return;
}
AnnotationAwareOrderComparator.sort(adapters);
ConfigurableBootstrapContext bootstrapContext = (ConfigurableBootstrapContext) event.getBootstrapContext();
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
for (EnvironmentPostProcessorAdapter adapter : adapters) {
adapter.onBootstrapContextClosed(bootstrapContext, applicationContext);
}
}
}
......@@ -5,38 +5,22 @@ import org.apache.commons.logging.Log;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @author liaozan
* @since 2021/11/22
*/
@Getter
public abstract class EnvironmentPostProcessorAdapter implements EnvironmentPostProcessor {
public abstract class EnvironmentPostProcessorLoggerAwareAdapter implements EnvironmentPostProcessor {
private final Log log;
private final DeferredLogFactory deferredLogFactory;
private final ConfigurableBootstrapContext bootstrapContext;
public EnvironmentPostProcessorAdapter(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext) {
public EnvironmentPostProcessorLoggerAwareAdapter(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext) {
this.log = logFactory.getLog(getClass());
this.bootstrapContext = bootstrapContext;
this.deferredLogFactory = logFactory;
this.addListener(this.bootstrapContext);
}
protected void onBootstrapContextClosed(ConfigurableBootstrapContext bootstrapContext, ConfigurableApplicationContext applicationContext) {
onBootstrapContextClosed(applicationContext);
}
protected void onBootstrapContextClosed(ConfigurableApplicationContext applicationContext) {
}
private void addListener(ConfigurableBootstrapContext bootstrapContext) {
BootstrapContextListenerComposite listener = BootstrapContextListenerComposite.getInstance();
listener.addListener(this);
bootstrapContext.addCloseListener(listener);
}
}
\ No newline at end of file
......@@ -5,10 +5,11 @@ import cn.hutool.core.util.ArrayUtil;
import com.schbrain.common.constants.DateTimeFormatters;
import com.schbrain.common.util.EnvUtils;
import com.schbrain.common.util.PortUtils;
import com.schbrain.framework.support.spring.EnvironmentPostProcessorAdapter;
import com.schbrain.framework.support.spring.EnvironmentPostProcessorLoggerAwareAdapter;
import org.springframework.boot.*;
import org.springframework.boot.actuate.autoconfigure.health.HealthProperties.Show;
import org.springframework.boot.actuate.info.InfoPropertiesInfoContributor.Mode;
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.boot.web.server.Shutdown;
import org.springframework.core.Ordered;
......@@ -22,7 +23,12 @@ import java.util.*;
* @author liaozan
* @since 2021/12/18
*/
public class DefaultPropertiesEnvironmentPostProcessor extends EnvironmentPostProcessorAdapter implements Ordered {
public class DefaultPropertiesEnvironmentPostProcessor extends EnvironmentPostProcessorLoggerAwareAdapter implements Ordered {
/**
* set default properties after configData loaded
*/
public static final Integer DEFAULT_ORDER = ConfigDataEnvironmentPostProcessor.ORDER + 1;
private static final String SPRING_PROFILE_ACTIVE = "spring.profiles.active";
private static final String DUBBO_REGISTER_KEY = "dubbo.registry.register";
......@@ -67,7 +73,7 @@ public class DefaultPropertiesEnvironmentPostProcessor extends EnvironmentPostPr
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
return DEFAULT_ORDER;
}
private void configureActiveProfileIfPresent(ConfigurableEnvironment environment, Map<String, Object> defaultProperties) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment