com.gitlab.spacetrucker.modularspringcontexts.module.ModularSpringContextsDynamicScopeBeanDefinitionParser Maven / Gradle / Ivy
Show all versions of modular-spring-contexts Show documentation
package com.gitlab.spacetrucker.modularspringcontexts.module;
import java.text.MessageFormat;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionValidationException;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.w3c.dom.Element;
import com.gitlab.spacetrucker.modularspringcontexts.SingletonBeanImportFactoryBean;
/**
* Bean definition parser that is able to determine the scope of the imported
* bean and therefore define the scope of the imported bean in the importing
* {@link ApplicationContext} as it was originally defined.
*
* This bean definition parser is also able to check whether a bean to be
* imported is marked as exported in the {@code ApplicationContext} from which
* it is imported. A bean definition can be marked as exported via a meta
* attribute named {@code exported} with value {@code true}. A value of false or
* the absence of this meta attribute will define the bean as not exported. The
* import of non-exported beans is not possible.
*/
public class ModularSpringContextsDynamicScopeBeanDefinitionParser extends AbstractBeanDefinitionParser
implements ApplicationContextAware {
private BeanFactory applicationContextBeanFactory;
private boolean checkVisibility;
/**
* Creates a bean definition for the bean to be imported by requesting
* required informations from the bean factory of the application context
* from which the bean is imported.
*
* @throws BeanDefinitionValidationException
* if this instance is configured to
* {@link #setCheckVisibility(boolean) check visibility} and the
* imported bean is not visible.
*/
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
String sourceModule = element.getAttribute("sourceModule");
String sourceBean = element.getAttribute("sourceBean");
if (sourceBean == null || sourceBean.length() == 0) {
sourceBean = element.getAttribute("id");
}
if (checkVisibility && !isVisible(sourceModule, sourceBean)) {
throw new BeanDefinitionValidationException(
MessageFormat.format("Bean {0} of module {1} is not exported.", sourceBean, sourceModule));
}
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(SingletonBeanImportFactoryBean.class);
MutablePropertyValues propertyValues = createPropertyValues(sourceModule, sourceBean);
beanDefinition.setPropertyValues(propertyValues);
beanDefinition.setScope(defineScope(sourceModule, sourceBean));
return beanDefinition;
}
private boolean isVisible(String sourceModule, String sourceBean) {
BeanDefinition definition = getBeanDefinition(sourceModule, sourceBean);
Object exportedAttribute = definition.getAttribute(ModularSpringContextsConstants.EXPORTED_META_ATTRIBUTE);
if (exportedAttribute instanceof String) {
return Boolean.parseBoolean((String) exportedAttribute);
}
return false;
}
private String defineScope(String sourceModule, String sourceBean) {
BeanDefinition beanDefinition = getBeanDefinition(sourceModule, sourceBean);
return beanDefinition.getScope();
}
private BeanDefinition getBeanDefinition(String sourceModule, String sourceBean) {
ConfigurableApplicationContext sourceModuleBean = applicationContextBeanFactory.getBean(sourceModule,
ConfigurableApplicationContext.class);
BeanDefinition beanDefinition = sourceModuleBean.getBeanFactory().getMergedBeanDefinition(sourceBean);
return beanDefinition;
}
private MutablePropertyValues createPropertyValues(String sourceModule, String sourceBean) {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("sourceModuleName", sourceModule);
propertyValues.addPropertyValue("sourceBeanName", sourceBean);
return propertyValues;
}
public void setApplicationContextBeanFactory(BeanFactory applicationContextBeanFactory) {
this.applicationContextBeanFactory = applicationContextBeanFactory;
}
public void setCheckVisibility(boolean checkVisibility) {
this.checkVisibility = checkVisibility;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
setApplicationContextBeanFactory(applicationContext);
}
}