diff --git a/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/actuate/autoconfigure/I18nEndpointAutoConfiguration.java b/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/actuate/autoconfigure/I18nEndpointAutoConfiguration.java index 1b15b57..7953281 100644 --- a/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/actuate/autoconfigure/I18nEndpointAutoConfiguration.java +++ b/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/actuate/autoconfigure/I18nEndpointAutoConfiguration.java @@ -18,9 +18,9 @@ import io.microsphere.i18n.spring.boot.actuate.I18nEndpoint; import io.microsphere.i18n.spring.boot.autoconfigure.I18nAutoConfiguration; +import io.microsphere.i18n.spring.boot.condition.ConditionalOnI18nEnabled; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -33,10 +33,9 @@ * @since 1.0.0 */ @ConditionalOnClass(name = { - "io.microsphere.i18n.ServiceMessageSource", // microsphere-i18n-core - "io.microsphere.i18n.spring.context.I18nConfiguration", // microsphere-i18n-spring "org.springframework.boot.actuate.endpoint.annotation.Endpoint", // spring-boot-actuator-autoconfigure }) +@ConditionalOnI18nEnabled @ConditionalOnAvailableEndpoint(endpoint = I18nEndpoint.class) @AutoConfigureAfter(I18nAutoConfiguration.class) public class I18nEndpointAutoConfiguration { diff --git a/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/autoconfigure/I18nAutoConfiguration.java b/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/autoconfigure/I18nAutoConfiguration.java index 389816f..9820c60 100644 --- a/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/autoconfigure/I18nAutoConfiguration.java +++ b/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/autoconfigure/I18nAutoConfiguration.java @@ -16,21 +16,20 @@ */ package io.microsphere.i18n.spring.boot.autoconfigure; -import io.microsphere.i18n.spring.context.I18nConfiguration; +import io.microsphere.i18n.spring.annotation.EnableI18n; +import io.microsphere.i18n.spring.boot.condition.ConditionalOnI18nEnabled; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.context.annotation.Import; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import static io.microsphere.i18n.spring.constants.I18nConstants.ENABLED_PROPERTY_NAME; /** * I18n Auto-Configuration * * @author Mercy - * @see I18nConfiguration * @since 1.0.0 */ -@ConditionalOnClass(name = { - "io.microsphere.i18n.ServiceMessageSource", // microsphere-i18n-core - "io.microsphere.i18n.spring.context.I18nConfiguration", // microsphere-i18n-spring -}) -@Import(I18nConfiguration.class) +@ConditionalOnI18nEnabled +@EnableI18n public class I18nAutoConfiguration { } diff --git a/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/condition/ConditionalOnI18nEnabled.java b/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/condition/ConditionalOnI18nEnabled.java new file mode 100644 index 0000000..6b1c20c --- /dev/null +++ b/microsphere-i18n-spring-boot/src/main/java/io/microsphere/i18n/spring/boot/condition/ConditionalOnI18nEnabled.java @@ -0,0 +1,31 @@ +package io.microsphere.i18n.spring.boot.condition; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Conditional; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static io.microsphere.i18n.spring.constants.I18nConstants.ENABLED_PROPERTY_NAME; + +/** + * {@link Conditional @Conditional} that checks whether the I18n enabled + * + * @author Mercy + * @since 1.0.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Documented +@ConditionalOnClass(name = { + "io.microsphere.i18n.ServiceMessageSource", // microsphere-i18n-core + "io.microsphere.i18n.spring.annotation.EnableI18n", // microsphere-i18n-spring +}) +@ConditionalOnProperty(name = ENABLED_PROPERTY_NAME, matchIfMissing = true) +public @interface ConditionalOnI18nEnabled { + +} diff --git a/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/EnableI18n.java b/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/EnableI18n.java index 631be0c..bc833cc 100644 --- a/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/EnableI18n.java +++ b/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/EnableI18n.java @@ -33,7 +33,10 @@ import static io.microsphere.i18n.ServiceMessageSource.COMMON_SOURCE; /** - * Enables the extension for Spring Internationalisation + * Enables the extension for Spring Internationalisation. + *
+ * The feature could be disabled by the Spring property if
+ * {@link I18nConstants#ENABLED_PROPERTY_NAME "microsphere.i18n.enabled"} is false
*
* @author Mercy
* @see I18nImportBeanDefinitionRegistrar
@@ -48,13 +51,20 @@
public @interface EnableI18n {
/**
- * Declares the sources of the {@link ServiceMessageSource} as the {@link ServiceMessageSourceFactoryBean} Spring Beans
- * to be registered.
+ * Declares the sources of the {@link ServiceMessageSource} to register the {@link ServiceMessageSourceFactoryBean}
+ * Spring Beans whose names are composed by their source content appending "ServiceMessageSource", the default value
+ * is {@value ServiceMessageSource#COMMON_SOURCE "common"} indicates that the named "commonServiceMessageSource"
+ * Spring Bean will be registered.
*
- * The attribute value will be merged from the Spring property whose name is {@link I18nConstants#SOURCES_PROPERTY_NAME} + * Besides the attribute value, the sources will be extended from the Spring property whose name is + * {@link I18nConstants#SOURCES_PROPERTY_NAME "microsphere.i18n.sources"}. + *
+ * Finally, all sourced {@link ServiceMessageSource} Spring Beans as the members will be composited into
+ * a Primary Spring Bean named {@link I18nConstants#SERVICE_MESSAGE_SOURCE_BEAN_NAME "serviceMessageSource"}.
*
- * @return {@link ServiceMessageSource#COMMON_SOURCE} as the default
+ * @return {@link ServiceMessageSource#COMMON_SOURCE "common"} as the default
* @see I18nConstants#SOURCES_PROPERTY_NAME
+ * @see I18nConstants#SERVICE_MESSAGE_SOURCE_BEAN_NAME
*/
String[] sources() default {COMMON_SOURCE};
diff --git a/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/I18nImportBeanDefinitionRegistrar.java b/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/I18nImportBeanDefinitionRegistrar.java
index d6aa5ad..b7bdd1d 100644
--- a/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/I18nImportBeanDefinitionRegistrar.java
+++ b/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/annotation/I18nImportBeanDefinitionRegistrar.java
@@ -22,6 +22,8 @@
import io.microsphere.i18n.spring.beans.factory.support.ServiceMessageSourceBeanLifecyclePostProcessor;
import io.microsphere.i18n.spring.context.I18nApplicationListener;
import io.microsphere.i18n.spring.context.MessageSourceAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
@@ -35,6 +37,8 @@
import java.util.Set;
import java.util.function.Supplier;
+import static io.microsphere.i18n.spring.constants.I18nConstants.DEFAULT_ENABLED;
+import static io.microsphere.i18n.spring.constants.I18nConstants.ENABLED_PROPERTY_NAME;
import static io.microsphere.i18n.spring.constants.I18nConstants.SERVICE_MESSAGE_SOURCE_BEAN_NAME;
import static io.microsphere.i18n.spring.constants.I18nConstants.SOURCES_PROPERTY_NAME;
import static io.microsphere.spring.util.BeanRegistrar.registerBeanDefinition;
@@ -55,15 +59,19 @@ public class I18nImportBeanDefinitionRegistrar implements ImportBeanDefinitionRe
private static final Class extends Annotation> ANNOTATION_TYPE = EnableI18n.class;
+ private static Logger logger = LoggerFactory.getLogger(ANNOTATION_TYPE);
+
private Environment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
- AnnotationAttributes attributes = fromMap(metadata.getAnnotationAttributes(ANNOTATION_TYPE.getName()));
- registerServiceMessageSourceBeanDefinitions(attributes, registry);
- registerMessageSourceAdapterBeanDefinition(attributes, registry);
- registerI18nApplicationListenerBeanDefinition(registry);
- registerBeanPostProcessorBeanDefinitions(registry);
+ if (isEnabled()) {
+ AnnotationAttributes attributes = fromMap(metadata.getAnnotationAttributes(ANNOTATION_TYPE.getName()));
+ registerServiceMessageSourceBeanDefinitions(attributes, registry);
+ registerMessageSourceAdapterBeanDefinition(attributes, registry);
+ registerI18nApplicationListenerBeanDefinition(registry);
+ registerBeanPostProcessorBeanDefinitions(registry);
+ }
}
private void registerServiceMessageSourceBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) {
@@ -112,4 +120,14 @@ private void registerBeanPostProcessorBeanDefinitions(BeanDefinitionRegistry reg
public void setEnvironment(Environment environment) {
this.environment = environment;
}
+
+ private boolean isEnabled() {
+ String propertyName = ENABLED_PROPERTY_NAME;
+ boolean enabled = environment.getProperty(propertyName, boolean.class, DEFAULT_ENABLED);
+ logger.debug("Microsphere i18n is {} , cased by the Spring property[name : '{}', default value : '{}']",
+ enabled ? "enabled" : "disabled",
+ propertyName,
+ DEFAULT_ENABLED);
+ return enabled;
+ }
}
diff --git a/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/context/I18nApplicationListener.java b/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/context/I18nApplicationListener.java
index c4dca27..959c24b 100644
--- a/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/context/I18nApplicationListener.java
+++ b/microsphere-i18n-spring/src/main/java/io/microsphere/i18n/spring/context/I18nApplicationListener.java
@@ -17,16 +17,25 @@
package io.microsphere.i18n.spring.context;
import io.microsphere.i18n.ServiceMessageSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.SmartApplicationListener;
+import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
+
+import java.util.List;
+import java.util.Locale;
import static io.microsphere.i18n.spring.constants.I18nConstants.SERVICE_MESSAGE_SOURCE_BEAN_NAME;
import static io.microsphere.i18n.util.I18nUtils.destroyServiceMessageSource;
import static io.microsphere.i18n.util.I18nUtils.setServiceMessageSource;
+import static io.microsphere.spring.util.BeanUtils.getOptionalBean;
+import static io.microsphere.spring.util.BeanUtils.getSortedBeans;
+import static io.microsphere.util.ClassLoaderUtils.resolveClass;
import static org.springframework.util.ObjectUtils.containsElement;
/**
@@ -38,6 +47,12 @@
*/
public class I18nApplicationListener implements SmartApplicationListener {
+ private static final Logger logger = LoggerFactory.getLogger(I18nApplicationListener.class);
+
+ private static final String ACCEPT_HEADER_LOCALE_RESOLVER_CLASS_NAME = "org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver";
+
+ private static final Class> ACCEPT_HEADER_LOCALE_RESOLVER_CLASS = resolveClass(ACCEPT_HEADER_LOCALE_RESOLVER_CLASS_NAME);
+
private static final Class>[] SUPPORTED_EVENT_TYPES = {
ContextRefreshedEvent.class,
ContextClosedEvent.class
@@ -60,11 +75,43 @@ public void onApplicationEvent(ApplicationEvent event) {
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
+ initializeServiceMessageSource(context);
+
+ initializeAcceptHeaderLocaleResolver(context);
+ }
+
+ private void initializeServiceMessageSource(ApplicationContext context) {
ServiceMessageSource serviceMessageSource = context.getBean(SERVICE_MESSAGE_SOURCE_BEAN_NAME, ServiceMessageSource.class);
setServiceMessageSource(serviceMessageSource);
}
+ private void initializeAcceptHeaderLocaleResolver(ApplicationContext context) {
+ if (ACCEPT_HEADER_LOCALE_RESOLVER_CLASS == null) {
+ logger.debug("The class '{}' was not found!", ACCEPT_HEADER_LOCALE_RESOLVER_CLASS_NAME);
+ return;
+ }
+
+ Class