-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3af6528
commit 20dbcee
Showing
8 changed files
with
299 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,8 +16,12 @@ | |
*/ | ||
package io.microsphere.i18n.spring.annotation; | ||
|
||
import io.microsphere.i18n.spring.context.I18nConfiguration; | ||
import io.microsphere.i18n.ServiceMessageSource; | ||
import io.microsphere.i18n.spring.beans.factory.ServiceMessageSourceFactoryBean; | ||
import io.microsphere.i18n.spring.constants.I18nConstants; | ||
import org.springframework.context.MessageSource; | ||
import org.springframework.context.annotation.Import; | ||
import org.springframework.context.support.AbstractApplicationContext; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
|
@@ -26,17 +30,41 @@ | |
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
import static io.microsphere.i18n.ServiceMessageSource.COMMON_SOURCE; | ||
|
||
/** | ||
* Enables the extension for Spring Internationalisation | ||
* | ||
* @author <a href="mailto:[email protected]">Mercy<a/> | ||
* @see I18nConfiguration | ||
* @see I18nImportBeanDefinitionRegistrar | ||
* @see ServiceMessageSourceFactoryBean | ||
* @since 1.0.0 | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) | ||
@Documented | ||
@Inherited | ||
@Import(I18nConfiguration.class) | ||
@Import(I18nImportBeanDefinitionRegistrar.class) | ||
public @interface EnableI18n { | ||
|
||
/** | ||
* Declares the sources of the {@link ServiceMessageSource} as the {@link ServiceMessageSourceFactoryBean} Spring Beans | ||
* to be registered. | ||
* <p> | ||
* The attribute value will be merged from the Spring property whose name is {@link I18nConstants#SOURCES_PROPERTY_NAME} | ||
* | ||
* @return {@link ServiceMessageSource#COMMON_SOURCE} as the default | ||
* @see I18nConstants#SOURCES_PROPERTY_NAME | ||
*/ | ||
String[] sources() default {COMMON_SOURCE}; | ||
|
||
/** | ||
* Whether to expose {@link I18nConstants#SERVICE_MESSAGE_SOURCE_BEAN_NAME the primary Spring Bean} | ||
* {@link ServiceMessageSource} as the {@link MessageSource} | ||
* | ||
* @return <code>true</code> as default | ||
* @see AbstractApplicationContext#MESSAGE_SOURCE_BEAN_NAME | ||
* @see MessageSource | ||
*/ | ||
boolean exposeMessageSource() default true; | ||
} |
115 changes: 115 additions & 0 deletions
115
...rc/main/java/io/microsphere/i18n/spring/annotation/I18nImportBeanDefinitionRegistrar.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.microsphere.i18n.spring.annotation; | ||
|
||
import io.microsphere.i18n.spring.DelegatingServiceMessageSource; | ||
import io.microsphere.i18n.spring.beans.factory.ServiceMessageSourceFactoryBean; | ||
import io.microsphere.i18n.spring.beans.factory.config.I18nBeanPostProcessor; | ||
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.springframework.beans.factory.config.BeanDefinition; | ||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; | ||
import org.springframework.context.EnvironmentAware; | ||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; | ||
import org.springframework.core.annotation.AnnotationAttributes; | ||
import org.springframework.core.env.Environment; | ||
import org.springframework.core.type.AnnotationMetadata; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.util.LinkedHashSet; | ||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
|
||
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; | ||
import static io.microsphere.util.ArrayUtils.EMPTY_STRING_ARRAY; | ||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition; | ||
import static org.springframework.context.support.AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME; | ||
import static org.springframework.core.annotation.AnnotationAttributes.fromMap; | ||
|
||
/** | ||
* I18n {@link ImportBeanDefinitionRegistrar} | ||
* | ||
* @author <a href="mailto:[email protected]">Mercy<a/> | ||
* @see ImportBeanDefinitionRegistrar | ||
* @see EnableI18n | ||
* @since 1.0.0 | ||
*/ | ||
public class I18nImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { | ||
|
||
private static final Class<? extends Annotation> ANNOTATION_TYPE = EnableI18n.class; | ||
|
||
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); | ||
} | ||
|
||
private void registerServiceMessageSourceBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) { | ||
Set<String> sources = resolveSources(attributes); | ||
|
||
for (String source : sources) { | ||
String beanName = source + "ServiceMessageSource"; | ||
registerBeanDefinition(registry, beanName, ServiceMessageSourceFactoryBean.class, source); | ||
} | ||
|
||
// Register DelegatingServiceMessageSource as the Spring Primary Bean | ||
BeanDefinition primaryBeanDefinition = rootBeanDefinition(DelegatingServiceMessageSource.class).setPrimary(true).getBeanDefinition(); | ||
registry.registerBeanDefinition(SERVICE_MESSAGE_SOURCE_BEAN_NAME, primaryBeanDefinition); | ||
} | ||
|
||
private Set<String> resolveSources(AnnotationAttributes attributes) { | ||
Set<String> sources = new LinkedHashSet<>(); | ||
initSources(sources, () -> environment.getProperty(SOURCES_PROPERTY_NAME, String[].class, EMPTY_STRING_ARRAY)); | ||
initSources(sources, () -> attributes.getStringArray("sources")); | ||
return sources; | ||
} | ||
|
||
private void initSources(Set<String> sources, Supplier<String[]> sourcesSupplier) { | ||
for (String source : sourcesSupplier.get()) { | ||
sources.add(environment.resolvePlaceholders(source)); | ||
} | ||
} | ||
|
||
private void registerMessageSourceAdapterBeanDefinition(AnnotationAttributes attributes, BeanDefinitionRegistry registry) { | ||
boolean exposeMessageSource = attributes.getBoolean("exposeMessageSource"); | ||
if (exposeMessageSource) { | ||
registerBeanDefinition(registry, MESSAGE_SOURCE_BEAN_NAME, MessageSourceAdapter.class); | ||
} | ||
} | ||
|
||
private void registerI18nApplicationListenerBeanDefinition(BeanDefinitionRegistry registry) { | ||
registerBeanDefinition(registry, I18nApplicationListener.class); | ||
} | ||
|
||
private void registerBeanPostProcessorBeanDefinitions(BeanDefinitionRegistry registry) { | ||
registerBeanDefinition(registry, I18nBeanPostProcessor.class); | ||
registerBeanDefinition(registry, ServiceMessageSourceBeanLifecyclePostProcessor.class); | ||
} | ||
|
||
@Override | ||
public void setEnvironment(Environment environment) { | ||
this.environment = environment; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
...i18n-spring/src/main/java/io/microsphere/i18n/spring/context/I18nApplicationListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You under the Apache License, Version 2.0 | ||
* (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.microsphere.i18n.spring.context; | ||
|
||
import io.microsphere.i18n.ServiceMessageSource; | ||
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 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 org.springframework.util.ObjectUtils.containsElement; | ||
|
||
/** | ||
* Internationalization {@link ApplicationListener} | ||
* | ||
* @author <a href="mailto:[email protected]">Mercy<a/> | ||
* @see SmartApplicationListener | ||
* @since 1.0.0 | ||
*/ | ||
public class I18nApplicationListener implements SmartApplicationListener { | ||
|
||
private static final Class<?>[] SUPPORTED_EVENT_TYPES = { | ||
ContextRefreshedEvent.class, | ||
ContextClosedEvent.class | ||
}; | ||
|
||
@Override | ||
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) { | ||
return containsElement(SUPPORTED_EVENT_TYPES, eventType); | ||
} | ||
|
||
@Override | ||
public void onApplicationEvent(ApplicationEvent event) { | ||
if (event instanceof ContextRefreshedEvent) { | ||
onContextRefreshedEvent((ContextRefreshedEvent) event); | ||
} else if (event instanceof ContextClosedEvent) { | ||
onContextClosedEvent((ContextClosedEvent) event); | ||
} | ||
} | ||
|
||
private void onContextRefreshedEvent(ContextRefreshedEvent event) { | ||
ApplicationContext context = event.getApplicationContext(); | ||
|
||
ServiceMessageSource serviceMessageSource = context.getBean(SERVICE_MESSAGE_SOURCE_BEAN_NAME, ServiceMessageSource.class); | ||
setServiceMessageSource(serviceMessageSource); | ||
} | ||
|
||
|
||
private void onContextClosedEvent(ContextClosedEvent event) { | ||
destroyServiceMessageSource(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,7 +37,9 @@ | |
* @author <a href="mailto:[email protected]">Mercy<a/> | ||
* @see EnableI18n | ||
* @since 1.0.0 | ||
* @deprecated use {@link EnableI18n} | ||
*/ | ||
@Deprecated | ||
@Import(value = { | ||
ServiceMessageSourceBeanLifecyclePostProcessor.class | ||
}) | ||
|
59 changes: 59 additions & 0 deletions
59
...phere-i18n-spring/src/test/java/io/microsphere/i18n/spring/annotation/EnableI18nTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package io.microsphere.i18n.spring.annotation; | ||
|
||
import io.microsphere.i18n.AbstractSpringTest; | ||
import io.microsphere.i18n.ServiceMessageSource; | ||
import io.microsphere.i18n.spring.beans.TestServiceMessageSourceConfiguration; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.test.context.ContextConfiguration; | ||
import org.springframework.test.context.junit4.SpringRunner; | ||
|
||
import java.util.Locale; | ||
|
||
import static io.microsphere.i18n.util.I18nUtils.serviceMessageSource; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertNull; | ||
import static org.junit.Assert.assertSame; | ||
|
||
/** | ||
* {@link EnableI18n} Test | ||
* | ||
* @author <a href="mailto:[email protected]">Mercy<a/> | ||
* @since 1.0.0 | ||
*/ | ||
@RunWith(SpringRunner.class) | ||
@ContextConfiguration(classes = { | ||
EnableI18nTest.class, | ||
TestServiceMessageSourceConfiguration.class | ||
}) | ||
@EnableI18n | ||
public class EnableI18nTest extends AbstractSpringTest { | ||
|
||
@Autowired | ||
private ServiceMessageSource serviceMessageSource; | ||
|
||
@Test | ||
public void testGetMessage() { | ||
// Testing Simplified Chinese | ||
// If the Message Code is "a" | ||
assertEquals("测试-a", serviceMessageSource.getMessage("a")); | ||
|
||
// The same is true for overloaded methods with Message Pattern arguments | ||
assertEquals("您好,World", serviceMessageSource.getMessage("hello", "World")); | ||
|
||
// Returns null if code does not exist | ||
assertNull(serviceMessageSource.getMessage("code-not-found")); | ||
|
||
// Test English, because the English Message resource does not exist | ||
assertEquals("Hello,World", serviceMessageSource.getMessage("hello", Locale.ENGLISH, "World")); | ||
|
||
// Returns null if code does not exist | ||
assertNull(serviceMessageSource.getMessage("code-not-found", Locale.US)); | ||
} | ||
|
||
@Test | ||
public void testCommonServiceMessageSource() { | ||
assertSame(serviceMessageSource(), serviceMessageSource); | ||
} | ||
} |