SGF-562 - Include attribute to enable BeanFactoryLocator support in Annotation config.

This commit is contained in:
John Blum
2016-11-07 14:41:27 -08:00
parent 63b7889676
commit bcce3c0351
5 changed files with 119 additions and 14 deletions

View File

@@ -89,8 +89,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
private static final AtomicBoolean CUSTOM_EDITORS_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
private static final AtomicBoolean PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED =
new AtomicBoolean(false);
private static final AtomicBoolean PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
protected static final boolean DEFAULT_CLOSE = true;
protected static final boolean DEFAULT_COPY_ON_READ = false;
@@ -271,7 +270,6 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
registerCustomEditorBeanFactoryPostProcessor(importMetadata);
registerDefinedIndexesApplicationListener(importMetadata);
registerDiskStoreDirectoryBeanPostProcessor(importMetadata);
registerPdxDiskStoreAwareBeanFactoryPostProcessor(importMetadata);
}
/**
@@ -302,6 +300,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
setLogLevel((String) cacheMetadataAttributes.get("logLevel"));
setName((String) cacheMetadataAttributes.get("name"));
setUseBeanFactoryLocator(Boolean.TRUE.equals(cacheMetadataAttributes.get("useBeanFactoryLocator")));
}
}
@@ -324,6 +323,8 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
setPdxPersistent(Boolean.TRUE.equals(enablePdxAttributes.get("persistent")));
setPdxReadSerialized(Boolean.TRUE.equals(enablePdxAttributes.get("readSerialized")));
setPdxSerializer(resolvePdxSerializer((String) enablePdxAttributes.get("serializerBeanName")));
registerPdxDiskStoreAwareBeanFactoryPostProcessor(importMetadata);
}
}
@@ -384,9 +385,13 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
/* (non-Javadoc) */
protected void registerPdxDiskStoreAwareBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
if (StringUtils.hasText(pdxDiskStoreName())) {
if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
.addConstructorArgValue(pdxDiskStoreName())
.getBeanDefinition());
}
}
}
@@ -504,7 +509,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
* @see #getAnnotationType()
*/
protected boolean isTypedCacheApplication(Class<? extends Annotation> annotationType,
AnnotationMetadata importMetadata) {
AnnotationMetadata importMetadata) {
return (annotationType.equals(getAnnotationType()) && importMetadata.hasAnnotation(getAnnotationTypeName()));
}

View File

@@ -28,6 +28,8 @@ import com.gemstone.gemfire.cache.control.ResourceManager;
import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.cache.server.ClientSubscriptionConfig;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.gemfire.server.SubscriptionEvictionPolicy;
@@ -42,7 +44,7 @@ import org.springframework.data.gemfire.server.SubscriptionEvictionPolicy;
* @author John Blum
* @see org.springframework.context.annotation.Configuration
* @see org.springframework.context.annotation.Import
* @see org.springframework.data.gemfire.config.annotation.PeerCacheConfiguration
* @see org.springframework.data.gemfire.config.annotation.CacheServerConfiguration
* @see com.gemstone.gemfire.cache.control.ResourceManager
* @see com.gemstone.gemfire.cache.server.CacheServer
* @see com.gemstone.gemfire.cache.server.ClientSubscriptionConfig
@@ -234,6 +236,15 @@ public @interface CacheServerApplication {
*/
SubscriptionEvictionPolicy subscriptionEvictionPolicy() default SubscriptionEvictionPolicy.NONE;
/**
* Determines whether the Spring {@link BeanFactoryLocator} should be enabled to lookup
* the Spring {@link BeanFactory} to auto-wire and configure/initialize GemFire components
* created in a non-Spring managed, GemFire context.
*
* Defaults to {@literal false}.
*/
boolean useBeanFactoryLocator() default false;
/**
* Configures whether this GemFire cache member node would pull it's configuration meta-data
* from the cluster-based Cluster Configuration service.

View File

@@ -27,6 +27,8 @@ import java.lang.annotation.Target;
import com.gemstone.gemfire.cache.client.PoolFactory;
import com.gemstone.gemfire.cache.control.ResourceManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.gemfire.GemfireUtils;
@@ -257,6 +259,15 @@ public @interface ClientCacheApplication {
*/
boolean threadLocalConnections() default PoolFactory.DEFAULT_THREAD_LOCAL_CONNECTIONS;
/**
* Determines whether the Spring {@link BeanFactoryLocator} should be enabled to lookup
* the Spring {@link BeanFactory} to auto-wire and configure/initialize GemFire components
* created in a non-Spring managed, GemFire context.
*
* Defaults to {@literal false}.
*/
boolean useBeanFactoryLocator() default false;
@interface Locator {
String host() default "localhost";

View File

@@ -26,6 +26,8 @@ import java.lang.annotation.Target;
import com.gemstone.gemfire.cache.control.ResourceManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -129,6 +131,15 @@ public @interface PeerCacheApplication {
*/
int searchTimeout() default 300;
/**
* Determines whether the Spring {@link BeanFactoryLocator} should be enabled to lookup
* the Spring {@link BeanFactory} to auto-wire and configure/initialize GemFire components
* created in a non-Spring managed, GemFire context.
*
* Defaults to {@literal false}.
*/
boolean useBeanFactoryLocator() default false;
/**
* Configures whether this GemFire cache member node would pull it's configuration meta-data
* from the cluster-based Cluster Configuration service.

View File

@@ -21,9 +21,13 @@ import java.util.Map;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -39,12 +43,14 @@ import org.springframework.util.StringUtils;
* of Pivotal GemFire and Apache Geode embedded services.
*
* @author John Blum
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar
* @see org.springframework.data.gemfire.config.annotation.AbstractCacheConfiguration
* @since 1.9.0
*/
@SuppressWarnings("unused")
public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanDefinitionRegistrar {
public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
public static final Integer DEFAULT_PORT = 0;
public static final String DEFAULT_HOST = "localhost";
@@ -53,6 +59,8 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
@SuppressWarnings("all")
private AbstractCacheConfiguration cacheConfiguration;
private BeanFactory beanFactory;
/**
* Returns a reference to an instance of the {@link AbstractCacheConfiguration} class used to configure
* a GemFire (Singleton, client or peer) cache instance along with it's associated, embedded services.
@@ -99,12 +107,32 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
return getAnnotationType().getSimpleName();
}
/**
* @inheritDoc
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
/**
* Returns a reference to the Spring {@link BeanFactory}.
*
* @return a reference to the Spring {@link BeanFactory}.
* @throws IllegalStateException if the Spring {@link BeanFactory} was not properly initialized.
* @see org.springframework.beans.factory.BeanFactory
*/
protected BeanFactory getBeanFactory() {
Assert.state(this.beanFactory != null, "BeanFactory was not properly initialized");
return this.beanFactory;
}
/**
* {@inheritDoc}
*/
@Override
public final void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
BeanDefinitionRegistry registry) {
if (isAnnotationPresent(importingClassMetadata)) {
Map<String, Object> annotationAttributes = getAnnotationAttributes(importingClassMetadata);
@@ -116,12 +144,12 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
/* (non-Javadoc) */
@SuppressWarnings("unused")
protected void registerBeanDefinitions(AnnotationMetadata importingClassMetaData,
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
}
/* (non-Javadoc) */
protected void setGemFireProperties(AnnotationMetadata importingClassMetadata,
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
Properties gemfireProperties = toGemFireProperties(annotationAttributes);
@@ -155,7 +183,7 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
/* (non-Javadoc) */
protected void registerGemFirePropertiesBeanPostProcessor(BeanDefinitionRegistry registry,
Properties customGemFireProperties) {
Properties customGemFireProperties) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
GemFirePropertiesBeanPostProcessor.class);
@@ -185,6 +213,38 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
return String.format("%1$s.%2$s", getClass().getName(), nameQualifier);
}
/**
* Resolves a Spring managed bean with the given {@link Class} type from the Spring {@link BeanFactory}.
*
* It is assumed that the given typed bean is the only bean of this {@link Class} type. If more than 1 bean
* of the given {@link Class} type is found, then the Spring {@link BeanFactory} will throw
* a {@link org.springframework.beans.factory.NoUniqueBeanDefinitionException}.
*
* If the {@link BeanFactory} is an instance of {@link AutowireCapableBeanFactory}, then the returned bean
* will also be configured.
*
* @param <T> {@link Class} type of the registered Spring managed bean.
* @param beanType required {@link Class} type of the registered Spring managed bean.
* @return a Spring managed bean instance for the given, required {@link Class} type, or {@literal null}
* if no bean instance of the given, required {@link Class} type could be found.
* @throws BeansException if the Spring manage bean of the required {@link Class} type could not be resolved.
* @see #getBeanFactory()
*/
@SuppressWarnings("unchecked")
protected <T> T resolveBean(Class<T> beanType) {
BeanFactory beanFactory = getBeanFactory();
if (beanFactory instanceof AutowireCapableBeanFactory) {
AutowireCapableBeanFactory autowiringBeanFactory = (AutowireCapableBeanFactory) beanFactory;
NamedBeanHolder<T> beanHolder = autowiringBeanFactory.resolveNamedBean(beanType);
return (T) autowiringBeanFactory.configureBean(beanHolder.getBeanInstance(), beanHolder.getBeanName());
}
else {
return beanFactory.getBean(beanType);
}
}
/* (non-Javadoc) */
protected String resolveHost(String hostname) {
return resolveHost(hostname, DEFAULT_HOST);
@@ -217,7 +277,14 @@ public abstract class EmbeddedServiceConfigurationSupport implements ImportBeanD
private final Properties gemfireProperties;
/* (non-Javadoc) */
/**
* Construct an instance of the {@link GemFirePropertiesBeanPostProcessor} initialized with
* the given GemFire {@link Properties}.
*
* @param gemfireProperties {@link Properties} used to configure GemFire.
* @throws IllegalArgumentException if the {@link Properties} are null or empty.
* @see java.util.Properties
*/
protected GemFirePropertiesBeanPostProcessor(Properties gemfireProperties) {
Assert.notEmpty(gemfireProperties, "GemFire Properties must not be null or empty");
this.gemfireProperties = gemfireProperties;