SGF-587 - Remove the GemfireBeanFactoryLocator and replace with SpringContextBootstrappingInitializer.
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import static org.springframework.data.gemfire.support.GemfireBeanFactoryLocator.newBeanFactoryLocator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -54,6 +56,7 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -139,15 +142,23 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
|
||||
|
||||
private TransactionWriter transactionWriter;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
initBeanFactoryLocator();
|
||||
postProcessBeforeCacheInitialization(resolveProperties());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void initBeanFactoryLocator() {
|
||||
if (useBeanFactoryLocator && beanFactoryLocator == null) {
|
||||
beanFactoryLocator = newBeanFactoryLocator(this.beanFactory, this.beanName);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void postProcessBeforeCacheInitialization(Properties gemfireProperties) {
|
||||
if (GemfireUtils.isGemfireVersion8OrAbove()) {
|
||||
@@ -180,9 +191,7 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
|
||||
|
||||
/* (non-Javadoc) */
|
||||
Cache init() throws Exception {
|
||||
initBeanFactoryLocator();
|
||||
|
||||
final ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
try {
|
||||
// use bean ClassLoader to load Spring configured, GemFire Declarable classes
|
||||
@@ -209,16 +218,6 @@ public class CacheFactoryBean implements BeanClassLoaderAware, BeanFactoryAware,
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void initBeanFactoryLocator() {
|
||||
if (useBeanFactoryLocator && beanFactoryLocator == null) {
|
||||
beanFactoryLocator = new GemfireBeanFactoryLocator();
|
||||
beanFactoryLocator.setBeanFactory(beanFactory);
|
||||
beanFactoryLocator.setBeanName(beanName);
|
||||
beanFactoryLocator.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If Dynamic Regions are enabled, create and initialize a DynamicRegionFactory before creating the Cache.
|
||||
*/
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.CacheCallback;
|
||||
import org.apache.geode.cache.Declarable;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||
|
||||
/**
|
||||
* Convenience class for Spring-aware GemFire Declarable components. Provides a reference to the current
|
||||
* Spring ApplicationContext, e.g. for Spring bean lookup or resource loading.
|
||||
*
|
||||
* Note that in most cases, one can just declare the same components as Spring beans, through {@link RegionFactoryBean}
|
||||
* which gives access to the full Spring container capabilities and does not enforce the {@link Declarable} interface
|
||||
* to be implemented.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.access.BeanFactoryReference
|
||||
* @see org.apache.geode.cache.CacheCallback
|
||||
* @see org.apache.geode.cache.Declarable
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class DeclarableSupport implements CacheCallback, Declarable {
|
||||
|
||||
private String beanFactoryKey = null;
|
||||
|
||||
private BeanFactoryReference beanFactoryReference = null;
|
||||
|
||||
public DeclarableSupport() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the configured Spring BeanFactory.
|
||||
*
|
||||
* @return a Spring BeanFactory reference.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return beanFactoryReference.getFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key under which the enclosing BeanFactory can be found. Needed only if multiple BeanFactories
|
||||
* are used with GemFire inside the same class loader / class space.
|
||||
*
|
||||
* @param key a String specifying the key used to lookup the "enclosing" BeanFactory in the presence
|
||||
* of multiple BeanFactories.
|
||||
* @see org.springframework.data.gemfire.GemfireBeanFactoryLocator
|
||||
*/
|
||||
public void setFactoryKey(String key) {
|
||||
this.beanFactoryKey = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* This Declarable implementation uses the init method as a lifecycle hook to initialize the bean factory locator.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.springframework.data.gemfire.GemfireBeanFactoryLocator
|
||||
* @see #setFactoryKey(String)
|
||||
*/
|
||||
@Override
|
||||
public final void init(Properties parameters) {
|
||||
beanFactoryReference = new GemfireBeanFactoryLocator().useBeanFactory(beanFactoryKey);
|
||||
initInstance(parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this Declarable object with the given Properties.
|
||||
*
|
||||
* @param props the Properties (parameters) used to initialize this Declarable.
|
||||
* @see org.apache.geode.cache.Declarable#init(java.util.Properties)
|
||||
* @see java.util.Properties
|
||||
* @see #init(Properties)
|
||||
*/
|
||||
protected void initInstance(Properties props) {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public void close() {
|
||||
beanFactoryReference.release();
|
||||
beanFactoryReference = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.access.BeanFactoryLocator;
|
||||
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link BeanFactoryLocator} used for storing Spring application context/bean factory for Gemfire
|
||||
* user components (or {@link org.apache.geode.cache.Declarable}. As opposed to the "traditional"
|
||||
* {@link org.springframework.beans.factory.access.SingletonBeanFactoryLocator} this implementation does
|
||||
* not require any configuration file; it rather assume declaration inside an application context
|
||||
* (usually through {@link org.apache.geode.cache.CacheFactory} which it will store under the name
|
||||
* and aliases of the bean (so the same "registry" can be used for storing multiple BeanFactories).
|
||||
* If there is only one BeanFactory registered then a null value can be used with {@link #setBeanName(String)}.
|
||||
*
|
||||
* In most cases, one does not need to use this class directly as it is used internally
|
||||
* by {@link org.apache.geode.cache.CacheFactory}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
*/
|
||||
public class GemfireBeanFactoryLocator implements BeanFactoryLocator, BeanFactoryAware, BeanNameAware, DisposableBean,
|
||||
InitializingBean {
|
||||
|
||||
private static final Log log = LogFactory.getLog(GemfireBeanFactoryLocator.class);
|
||||
|
||||
// alias/bean name <-> BeanFactory lookup
|
||||
private static final ConcurrentMap<String, BeanFactory> beanFactories = new ConcurrentHashMap<String, BeanFactory>();
|
||||
|
||||
// default factory to return
|
||||
private static volatile boolean canUseDefaultBeanFactory = true;
|
||||
private static volatile BeanFactory defaultFactory = null;
|
||||
|
||||
private static class SimpleBeanFactoryReference implements BeanFactoryReference {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
SimpleBeanFactoryReference(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public BeanFactory getFactory() {
|
||||
Assert.state(beanFactory != null, "The BeanFactory has already been released or closed");
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
public void release() throws FatalBeanException {
|
||||
beanFactory = null;
|
||||
}
|
||||
}
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private String[] names;
|
||||
|
||||
// default factory name
|
||||
private String factoryName = GemfireBeanFactoryLocator.class.getName();
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
// add the factory as default if possible (if it's the only one)
|
||||
synchronized (GemfireBeanFactoryLocator.class) {
|
||||
canUseDefaultBeanFactory = beanFactories.isEmpty();
|
||||
if (canUseDefaultBeanFactory) {
|
||||
if (defaultFactory == null) {
|
||||
defaultFactory = beanFactory;
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("default beanFactoryReference=" + defaultFactory);
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("more then one beanFactory - default not possible to determine");
|
||||
canUseDefaultBeanFactory = false;
|
||||
defaultFactory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add aliases
|
||||
if (StringUtils.hasText(factoryName)) {
|
||||
String[] aliases = beanFactory.getAliases(factoryName);
|
||||
names = ObjectUtils.addObjectToArray(aliases, factoryName);
|
||||
|
||||
for (String name : names) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("adding key=" + name + " w/ reference=" + beanFactory);
|
||||
|
||||
if (beanFactories.containsKey(name) && !beanFactory.equals(beanFactories.get(name))
|
||||
|| beanFactories.putIfAbsent(name, beanFactory) != null) {
|
||||
throw new IllegalArgumentException("a beanFactoryReference already exists for key " + factoryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (names != null) {
|
||||
for (String name : names) {
|
||||
beanFactories.remove(name);
|
||||
}
|
||||
}
|
||||
if (beanFactory == defaultFactory) {
|
||||
synchronized (GemfireBeanFactoryLocator.class) {
|
||||
defaultFactory = null;
|
||||
canUseDefaultBeanFactory = beanFactories.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BeanFactoryReference useBeanFactory(final String factoryKey) throws BeansException {
|
||||
// see if there is a default FactoryBean
|
||||
BeanFactory factory;
|
||||
|
||||
if (!StringUtils.hasText(factoryKey)) {
|
||||
if (!canUseDefaultBeanFactory)
|
||||
throw new IllegalArgumentException(
|
||||
"a non-null factoryKey needs to be specified as there are more then one factoryKeys available; "
|
||||
+ beanFactories.keySet());
|
||||
factory = defaultFactory;
|
||||
}
|
||||
else {
|
||||
factory = beanFactories.get(factoryKey);
|
||||
if (factory == null)
|
||||
throw new IllegalArgumentException("there is no beanFactory under key " + factoryKey);
|
||||
}
|
||||
|
||||
return new SimpleBeanFactoryReference(factory);
|
||||
}
|
||||
|
||||
public void setBeanName(String name) {
|
||||
factoryName = name;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,324 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.geode.cache.Declarable;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
import org.springframework.beans.factory.wiring.BeanWiringInfo;
|
||||
import org.springframework.beans.factory.wiring.BeanWiringInfoResolver;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The LazyWiringDeclarableSupport class is an implementation of the GemFire Declarable interface that enables support
|
||||
* for wiring GemFire components with Spring bean dependencies defined in the Spring context.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Properties
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.beans.factory.wiring.BeanWiringInfo
|
||||
* @see org.springframework.beans.factory.wiring.BeanWiringInfoResolver
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
* @see org.springframework.context.event.ContextRefreshedEvent
|
||||
* @see org.springframework.data.gemfire.DeclarableSupport
|
||||
* @see org.springframework.data.gemfire.WiringDeclarableSupport
|
||||
* @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer
|
||||
* @see org.apache.geode.cache.Declarable
|
||||
* @since 1.3.4
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class LazyWiringDeclarableSupport implements ApplicationListener<ContextRefreshedEvent>, Declarable,
|
||||
DisposableBean {
|
||||
|
||||
// name of the template bean defined in the Spring context for wiring this Declarable instance.
|
||||
protected static final String BEAN_NAME_PARAMETER = "bean-name";
|
||||
|
||||
// atomic reference to the parameter passed by GemFire when this Declarable was constructed
|
||||
// and the init method was called.
|
||||
private final AtomicReference<Properties> parametersReference = new AtomicReference<Properties>();
|
||||
|
||||
// condition determining the initialization state of this Declarable
|
||||
volatile boolean initialized = false;
|
||||
|
||||
private BeanFactoryReference beanFactoryReference = null;
|
||||
|
||||
private String factoryKey = null;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the LazyWiringDeclarableSupport class registered with the
|
||||
* SpringContextBootstrappingInitializer. This Declarable will receive notifications from the
|
||||
* SpringContextBootstrappingInitializer when the Spring context is created and initialized (refreshed).
|
||||
* The notification is necessary in order for this Declarable component to be configured and properly initialized
|
||||
* with any required Spring bean dependencies.
|
||||
*
|
||||
* @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer
|
||||
* #register(org.springframework.context.ApplicationListener)
|
||||
*/
|
||||
public LazyWiringDeclarableSupport() {
|
||||
SpringContextBootstrappingInitializer.register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key used to locate (lookup) the Spring BeanFactory.
|
||||
*
|
||||
* @param factoryKey the key used to locate the Spring BeanFactory.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.data.gemfire.GemfireBeanFactoryLocator
|
||||
* @see #getFactoryKey()
|
||||
*/
|
||||
public final void setFactoryKey(final String factoryKey) {
|
||||
this.factoryKey = factoryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key used to locate (lookup) the Spring BeanFactory.
|
||||
*
|
||||
* @return the key used to locate the Spring BeanFactory.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.data.gemfire.GemfireBeanFactoryLocator
|
||||
* @see #setFactoryKey(String)
|
||||
*/
|
||||
protected String getFactoryKey() {
|
||||
return factoryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that this Declarable object has been properly configured and initialized by the Spring container
|
||||
* after GemFire has constructed this Declarable object during startup. It is recommended to call this method
|
||||
* in any GemFire CacheCallback/Declarable object operational method (e.g. CacheLoader.load(..)) before use
|
||||
* in order to ensure that this Declarable was properly constructed, configured and initialized.
|
||||
*
|
||||
* @throws IllegalStateException if the Declarable object has not been properly configured or initialized
|
||||
* by the Spring container.
|
||||
* @see #init(java.util.Properties)
|
||||
* @see #isInitialized()
|
||||
*/
|
||||
protected void assertInitialized() {
|
||||
Assert.state(isInitialized(), String.format(
|
||||
"This Declarable object (%1$s) has not been properly configured and initialized",
|
||||
getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that this Declarable object has not yet been used, or activated prior to being fully configured
|
||||
* and initialized. It is possible, though rare, that the init(:Properties) might be called multiple times
|
||||
* by GemFire before the Spring container configure, initializes and puts this component to use.
|
||||
*
|
||||
* @throws java.lang.IllegalStateException if the Declarable object has already been configured and initialized
|
||||
* by the Spring container.
|
||||
* @see #init(java.util.Properties)
|
||||
* @see #isInitialized()
|
||||
*/
|
||||
protected void assertUninitialized() {
|
||||
Assert.state(!isInitialized(), String.format(
|
||||
"This Declarable object (%1$s) has already been configured and initialized",
|
||||
getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual configuration and initialization of this Declarable object before use. This method
|
||||
* is triggered by an ApplicationEvent (specifically, the ContextRefreshedEvent) indicating that the Spring context
|
||||
* has been created and refreshed.
|
||||
*
|
||||
* @param beanFactory the ConfigurableListableBeanFactory used to configure and initialize this Declarable GemFire
|
||||
* component.
|
||||
* @param parameters Properties instance containing the parameters from GemFire's configuration file
|
||||
* (e.g. cache.xml) to configure and initialize this Declarable object.
|
||||
* @throws IllegalArgumentException if the bean-name parameter was specified in GemFire configuration meta-data
|
||||
* but no bean with the specified name could be found in the Spring context.
|
||||
* @see #init(java.util.Properties)
|
||||
* @see #doPostInit(java.util.Properties)
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.beans.factory.wiring.BeanWiringInfo
|
||||
* @see org.springframework.beans.factory.wiring.BeanWiringInfoResolver
|
||||
*/
|
||||
void doInit(final BeanFactory beanFactory, final Properties parameters) {
|
||||
synchronized (this) {
|
||||
if (isNotInitialized()) {
|
||||
BeanConfigurerSupport beanConfigurer = new BeanConfigurerSupport();
|
||||
|
||||
beanConfigurer.setBeanFactory(beanFactory);
|
||||
|
||||
final String templateBeanName = parameters.getProperty(BEAN_NAME_PARAMETER);
|
||||
|
||||
if (StringUtils.hasText(templateBeanName)) {
|
||||
if (beanFactory.containsBean(templateBeanName)) {
|
||||
beanConfigurer.setBeanWiringInfoResolver(new BeanWiringInfoResolver() {
|
||||
@Override public BeanWiringInfo resolveWiringInfo(final Object beanInstance) {
|
||||
return new BeanWiringInfo(templateBeanName);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"No bean with name '%1$s' was found in the Spring context '%2$s'.", templateBeanName, beanFactory));
|
||||
}
|
||||
}
|
||||
|
||||
beanConfigurer.afterPropertiesSet();
|
||||
beanConfigurer.configureBean(this);
|
||||
beanConfigurer.destroy();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
doPostInit(parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default no operation method performed post initialization of this Declarable GemFire component to be overridden
|
||||
* by subclasses for application specific extension and behavior.
|
||||
*
|
||||
* @param parameters Properties instance containing the parameters from GemFire's configuration file
|
||||
* (e.g. cache.xml) to configure and initialize this Declarable object.
|
||||
* @see #doInit(BeanFactory, Properties)
|
||||
*/
|
||||
protected void doPostInit(final Properties parameters) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization method called by GemFire with configured parameters once this Declarable object has been
|
||||
* constructed during GemFire startup using an <initalizer> element in GemFire's configuration meta-data.
|
||||
*
|
||||
* @param parameters the configured parameters passed from the GemFire configuration (e.g. cache.xml) to this
|
||||
* Declarable as a Properties instance.
|
||||
* @throws IllegalStateException if this Declarable object has already been configured/initialized
|
||||
* by the Spring container and is currently active.
|
||||
* @see #doInit(BeanFactory, Properties)
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
@Override
|
||||
public final void init(final Properties parameters) {
|
||||
parametersReference.set(parameters);
|
||||
|
||||
try {
|
||||
doInit(locateBeanFactory(getFactoryKey()), nullSafeGetParameters());
|
||||
}
|
||||
catch (IllegalStateException ignore) {
|
||||
// the BeanFactory does not exist or has been released and or closed, so ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this Declarable object has been configured and initialized (i.e. the doInit method
|
||||
* has been called) by the Spring container.
|
||||
*
|
||||
* @return a boolean value indicating whether this Declarable object has been configured and initialized
|
||||
* by the Spring container.
|
||||
* @see #assertInitialized()
|
||||
* @see #doInit(BeanFactory, Properties)
|
||||
*/
|
||||
protected boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this Declarable object has been configured and initialized (i.e. the doInit method
|
||||
* has been called) by the Spring container.
|
||||
*
|
||||
* @return a boolean value indicating whether this Declarable object has been configured and initialized
|
||||
* by the Spring container.
|
||||
* @see #doInit(BeanFactory, Properties)
|
||||
* @see #isInitialized()
|
||||
*/
|
||||
protected boolean isNotInitialized() {
|
||||
return !isInitialized();
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates an existing Spring BeanFactory.
|
||||
*
|
||||
* @param factoryKey the key used to locate (lookup) the Spring BeanFactory.
|
||||
* @return a reference to the Spring BeanFactory if it exists.
|
||||
* @throws IllegalStateException if the BeanFactory has already been released or closed.
|
||||
* @see org.springframework.data.gemfire.GemfireBeanFactoryLocator
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory locateBeanFactory(String factoryKey) {
|
||||
if (beanFactoryReference == null) {
|
||||
beanFactoryReference = new GemfireBeanFactoryLocator().useBeanFactory(factoryKey);
|
||||
}
|
||||
|
||||
return beanFactoryReference.getFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to return the parameters passed to this Declarable object when created by GemFire from it's
|
||||
* configuration meta-data.
|
||||
*
|
||||
* @return a Properties object containing the a parameters specified for this Declarable, or an
|
||||
* empty Properties object if no parameters were supplied.
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
protected Properties nullSafeGetParameters() {
|
||||
Properties parameters = parametersReference.get();
|
||||
return (parameters != null ? parameters : new Properties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler method called when GemFire has created and initialized (refreshed) the Spring ApplicationContext
|
||||
* using the SpringContextBootstrappingInitializer Declarable class.
|
||||
*
|
||||
* @param event the ContextRefreshedEvent published by the Spring ApplicationContext after it is successfully
|
||||
* created and initialized by GemFire.
|
||||
* @throws IllegalArgumentException if the ApplicationContext is not an instance of ConfigurableApplicationContext.
|
||||
* @see #doInit(BeanFactory, Properties)
|
||||
* @see #nullSafeGetParameters()
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
* @see org.springframework.context.event.ContextRefreshedEvent
|
||||
*/
|
||||
@Override
|
||||
public final void onApplicationEvent(final ContextRefreshedEvent event) {
|
||||
Assert.isTrue(event.getApplicationContext() instanceof ConfigurableApplicationContext, String.format(
|
||||
"The Spring ApplicationContext (%1$s) must be an instance of ConfigurableApplicationContext",
|
||||
ObjectUtils.nullSafeClassName(event.getApplicationContext())));
|
||||
|
||||
doInit(((ConfigurableApplicationContext) event.getApplicationContext()).getBeanFactory(),
|
||||
nullSafeGetParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* When this bean gets destroyed by the Spring container, make sure this component gets unregistered from the
|
||||
* SpringContextBootstrappingInitializer.
|
||||
*
|
||||
* @throws Exception if bean destruction is unsuccessful.
|
||||
* @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer
|
||||
* #unregister(org.springframework.context.ApplicationListener)
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
SpringContextBootstrappingInitializer.unregister(this);
|
||||
beanFactoryReference.release();
|
||||
parametersReference.set(null);
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.Declarable;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
import org.springframework.beans.factory.wiring.BeanWiringInfo;
|
||||
import org.springframework.beans.factory.wiring.BeanWiringInfoResolver;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Dedicated {@link Declarable} support class for wiring the declaring instance through the Spring container.
|
||||
*
|
||||
* <p>This implementation first looks for a 'bean-name' property which will be used to locate a 'template'
|
||||
* bean definition. Autowiring will be performed, based on the settings defined in the Spring container.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.beans.factory.wiring.BeanWiringInfo
|
||||
* @see org.springframework.data.gemfire.DeclarableSupport
|
||||
* @see org.springframework.data.gemfire.LazyWiringDeclarableSupport
|
||||
* @see org.apache.geode.cache.Declarable
|
||||
* @deprecated please use LazyWiringDeclarableSupport instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class WiringDeclarableSupport extends DeclarableSupport {
|
||||
|
||||
private static final String BEAN_NAME_PROPERTY = "bean-name";
|
||||
|
||||
@Override
|
||||
protected void initInstance(Properties parameters) {
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
|
||||
BeanConfigurerSupport beanConfigurer = new BeanConfigurerSupport();
|
||||
beanConfigurer.setBeanFactory(beanFactory);
|
||||
|
||||
final String beanName = parameters.getProperty(BEAN_NAME_PROPERTY);
|
||||
|
||||
if (StringUtils.hasText(beanName)) {
|
||||
if (!beanFactory.containsBean(beanName)) {
|
||||
throw new IllegalArgumentException(String.format("Cannot find bean named '%1$s'", beanName));
|
||||
}
|
||||
|
||||
beanConfigurer.setBeanWiringInfoResolver(new BeanWiringInfoResolver() {
|
||||
public BeanWiringInfo resolveWiringInfo(Object beanInstance) {
|
||||
return new BeanWiringInfo(beanName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beanConfigurer.afterPropertiesSet();
|
||||
beanConfigurer.configureBean(this);
|
||||
beanConfigurer.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import org.apache.geode.cache.control.ResourceManager;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
import org.apache.geode.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;
|
||||
@@ -236,7 +235,7 @@ public @interface CacheServerApplication {
|
||||
SubscriptionEvictionPolicy subscriptionEvictionPolicy() default SubscriptionEvictionPolicy.NONE;
|
||||
|
||||
/**
|
||||
* Determines whether the Spring {@link BeanFactoryLocator} should be enabled to lookup
|
||||
* Determines whether the Spring {@link BeanFactory} locator 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.
|
||||
*
|
||||
|
||||
@@ -27,10 +27,10 @@ import java.lang.annotation.Target;
|
||||
import org.apache.geode.cache.client.PoolFactory;
|
||||
import org.apache.geode.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;
|
||||
import org.springframework.data.gemfire.support.GemfireBeanFactoryLocator;
|
||||
|
||||
/**
|
||||
* The {@link ClientCacheApplication} annotation enables a Spring Data GemFire based application to become
|
||||
@@ -259,7 +259,7 @@ public @interface ClientCacheApplication {
|
||||
boolean threadLocalConnections() default PoolFactory.DEFAULT_THREAD_LOCAL_CONNECTIONS;
|
||||
|
||||
/**
|
||||
* Determines whether the Spring {@link BeanFactoryLocator} should be enabled to lookup
|
||||
* Determines whether the {@link GemfireBeanFactoryLocator} 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.
|
||||
*
|
||||
|
||||
@@ -26,9 +26,9 @@ import java.lang.annotation.Target;
|
||||
|
||||
import org.apache.geode.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.support.GemfireBeanFactoryLocator;
|
||||
|
||||
/**
|
||||
* The {@link PeerCacheApplication} annotation enables an embedded GemFire peer {@link org.apache.geode.cache.Cache}
|
||||
@@ -131,7 +131,7 @@ public @interface PeerCacheApplication {
|
||||
int searchTimeout() default 300;
|
||||
|
||||
/**
|
||||
* Determines whether the Spring {@link BeanFactoryLocator} should be enabled to lookup
|
||||
* Determines whether the {@link GemfireBeanFactoryLocator} 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.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire.support;
|
||||
|
||||
import static org.springframework.data.gemfire.support.GemfireBeanFactoryLocator.newBeanFactoryLocator;
|
||||
|
||||
import org.apache.geode.cache.CacheCallback;
|
||||
import org.apache.geode.cache.Declarable;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.data.gemfire.RegionFactoryBean;
|
||||
|
||||
/**
|
||||
* Convenience class for Spring-aware GemFire {@link Declarable} components. Provides subclasses with a reference
|
||||
* to the current Spring {@link BeanFactory} in orde to perform Spring bean lookups or resource loading.
|
||||
*
|
||||
* Note, in most cases, the developer should just declare the same components as Spring beans in the Spring container,
|
||||
* through {@link RegionFactoryBean}, which gives access to the full Spring container capabilities and does not
|
||||
* enforce the {@link Declarable} interface to be implemented.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator
|
||||
* @see org.apache.geode.cache.CacheCallback
|
||||
* @see org.apache.geode.cache.Declarable
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class DeclarableSupport implements CacheCallback, Declarable {
|
||||
|
||||
private String beanFactoryKey = null;
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @return a reference to the Spring {@link BeanFactory}.
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#useBeanFactory(String)
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see #locateBeanFactory()
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return locateBeanFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key used to lookup the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @param beanFactoryKey {@link String} containing the key used to lookup the Spring {@link BeanFactory}.
|
||||
*/
|
||||
public void setBeanFactoryKey(String beanFactoryKey) {
|
||||
this.beanFactoryKey = beanFactoryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key used to lookup the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @return a {@link String} containing the key used to lookup the Spring {@link BeanFactory}.
|
||||
*/
|
||||
protected String getBeanFactoryKey() {
|
||||
return this.beanFactoryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @return a reference to the Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see #locateBeanFactory(String)
|
||||
* @see #getBeanFactoryKey()
|
||||
*/
|
||||
protected BeanFactory locateBeanFactory() {
|
||||
return locateBeanFactory(getBeanFactoryKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the Spring {@link BeanFactory} for the given {@code beanFactoryKey}.
|
||||
*
|
||||
* @param beanFactoryKey {@link String} containing the key used to lookup the Spring {@link BeanFactory}.
|
||||
* @return a reference to the Spring {@link BeanFactory} for the given {@code beanFactoryKey}.
|
||||
* @see org.springframework.data.gemfire.support.GemfireBeanFactoryLocator#useBeanFactory(String)
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory locateBeanFactory(String beanFactoryKey) {
|
||||
return newBeanFactoryLocator().useBeanFactory(beanFactoryKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire.support;
|
||||
|
||||
import static org.springframework.data.gemfire.support.GemfireBeanFactoryLocator.BeanFactoryReference.newBeanFactoryReference;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeSet;
|
||||
import static org.springframework.data.gemfire.util.SpringUtils.nullOrEquals;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The {@link GemfireBeanFactoryLocator} class stores a reference to the Spring
|
||||
* {@link org.springframework.context.ApplicationContext} / {@link BeanFactory} needed to auto-wire
|
||||
* user application GemFire objects implementing the {@link org.apache.geode.cache.Declarable} interface
|
||||
* and defined in GemFire's native configuration format (e.g. {@literal cache.xml}.
|
||||
*
|
||||
* In most cases, a developer does not need to use this class directly as it is registered by the
|
||||
* {@link org.springframework.data.gemfire.CacheFactoryBean} when the {@literal useBeanFactoryLocator} property
|
||||
* is set, and used internally by bothe the {@link WiringDeclarableSupport} and {@link LazyWiringDeclarableSupport}
|
||||
* SDG classes.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see LazyWiringDeclarableSupport
|
||||
* @see WiringDeclarableSupport
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class GemfireBeanFactoryLocator implements BeanFactoryAware, BeanNameAware, DisposableBean, InitializingBean {
|
||||
|
||||
// bean alias/name <-> BeanFactory mapping
|
||||
protected static final ConcurrentMap<String, BeanFactory> BEAN_FACTORIES = new ConcurrentHashMap<>();
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private Set<String> associatedBeanNameWithAliases = Collections.emptySet();
|
||||
|
||||
private String associatedBeanName;
|
||||
|
||||
/**
|
||||
* Factory method to construct a new, initialized instance of {@link GemfireBeanFactoryLocator}.
|
||||
*
|
||||
* @return a new, initialized instance of the {@link GemfireBeanFactoryLocator}.
|
||||
* @see GemfireBeanFactoryLocator
|
||||
* @see #GemfireBeanFactoryLocator()
|
||||
* @see #afterPropertiesSet()
|
||||
*/
|
||||
public static GemfireBeanFactoryLocator newBeanFactoryLocator() {
|
||||
GemfireBeanFactoryLocator beanFactoryLocator = new GemfireBeanFactoryLocator();
|
||||
beanFactoryLocator.afterPropertiesSet();
|
||||
return beanFactoryLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to construct a new, initialized instance of {@link GemfireBeanFactoryLocator} with the given
|
||||
* default Spring {@link BeanFactory} and associated Spring bean name.
|
||||
*
|
||||
* @param beanFactory reference to the {@link BeanFactory} used to resolve Spring bean references.
|
||||
* @param associatedBeanName {@link String} contain the name of the Spring bean associated with
|
||||
* the Spring {@link BeanFactory}.
|
||||
* @return a new, initialized instance of {@link GemfireBeanFactoryLocator} with the given default
|
||||
* Spring {@link BeanFactory} and associated Spring bean name.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see GemfireBeanFactoryLocator
|
||||
* @see #GemfireBeanFactoryLocator()
|
||||
* @see #setBeanFactory(BeanFactory)
|
||||
* @see #setBeanName(String)
|
||||
* @see #afterPropertiesSet()
|
||||
*/
|
||||
public static GemfireBeanFactoryLocator newBeanFactoryLocator(BeanFactory beanFactory, String associatedBeanName) {
|
||||
Assert.isTrue(beanFactory == null || StringUtils.hasText(associatedBeanName),
|
||||
"associatedBeanName must be specified when BeanFactory is not null");
|
||||
|
||||
GemfireBeanFactoryLocator beanFactoryLocator = new GemfireBeanFactoryLocator();
|
||||
|
||||
beanFactoryLocator.setBeanFactory(beanFactory);
|
||||
beanFactoryLocator.setBeanName(associatedBeanName);
|
||||
beanFactoryLocator.afterPropertiesSet();
|
||||
|
||||
return beanFactoryLocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link BeanFactory} mapped to the given {@code beanFactoryKey}.
|
||||
*
|
||||
* @param beanFactoryKey {@link String} value containing the key used to lookup the {@link BeanFactory}.
|
||||
* @return the {@link BeanFactory} mapped to the given key.
|
||||
* @throws IllegalArgumentException if a Spring {@link BeanFactory} could not be found
|
||||
* for the given {@code beanFactoryKey}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected static BeanFactory resolveBeanFactory(String beanFactoryKey) {
|
||||
BeanFactory beanFactory = BEAN_FACTORIES.get(beanFactoryKey);
|
||||
|
||||
Assert.isTrue(BEAN_FACTORIES.isEmpty() || beanFactory != null,
|
||||
String.format("BeanFactory for key [%s] was not found", beanFactoryKey));
|
||||
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a single Spring {@link BeanFactory} from the mapping of registered bean factories.
|
||||
*
|
||||
* This class method is synchronized because it contains a "compound action", even though separate actions
|
||||
* are performed on a {@link ConcurrentMap}, the actions are not independent and therefore must operate
|
||||
* atomically.
|
||||
*
|
||||
* @return a single Spring {@link BeanFactory} from the registry.
|
||||
* @throws IllegalStateException if the registry contains more than 1, or no
|
||||
* Spring {@link BeanFactory bean factories}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected static synchronized BeanFactory resolveSingleBeanFactory() {
|
||||
if (!BEAN_FACTORIES.isEmpty()) {
|
||||
boolean allTheSameBeanFactory = true;
|
||||
|
||||
BeanFactory currentBeanFactory = null;
|
||||
|
||||
for (BeanFactory beanFactory : BEAN_FACTORIES.values()) {
|
||||
allTheSameBeanFactory &= nullOrEquals(currentBeanFactory, beanFactory);
|
||||
currentBeanFactory = beanFactory;
|
||||
|
||||
if (!allTheSameBeanFactory) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.state(allTheSameBeanFactory, String.format(
|
||||
"BeanFactory key must be specified when more than one BeanFactory %s is registered",
|
||||
new TreeSet(BEAN_FACTORIES.keySet()).toString()));
|
||||
|
||||
return BEAN_FACTORIES.values().iterator().next();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all the provided names for given Spring {@link BeanFactory}.
|
||||
*
|
||||
* @param names {@link Set} of names and aliases to associate with the Spring {@link BeanFactory}.
|
||||
* @param beanFactory reference to the Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @throws IllegalArgumentException if {@link BeanFactory} is {@literal null}.
|
||||
* @throws IllegalStateException if one of the provided names is already associated with
|
||||
* an existing, other than given, Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected static synchronized void registerAliases(Set<String> names, BeanFactory beanFactory) {
|
||||
Assert.isTrue(nullSafeSet(names).isEmpty() || beanFactory != null,
|
||||
"BeanFactory must not be null when aliases are specified");
|
||||
|
||||
for (String name : nullSafeSet(names)) {
|
||||
BeanFactory existingBeanFactory = BEAN_FACTORIES.putIfAbsent(name, beanFactory);
|
||||
|
||||
Assert.isTrue(nullOrEquals(existingBeanFactory, beanFactory),
|
||||
String.format("BeanFactory reference already exists for key [%s]", name));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all Spring {@link BeanFactory} associations/mappings for the given {@link Set} of names.
|
||||
*
|
||||
* @param names {@link Set} of names identifying the associations/mappings to remove.
|
||||
* @return a boolean value indicating whether all associations/mappings were removed successfully.
|
||||
*/
|
||||
protected static synchronized boolean unregisterAliases(Set<String> names) {
|
||||
return BEAN_FACTORIES.keySet().removeAll(names);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
BeanFactory beanFactory = getBeanFactory();
|
||||
|
||||
registerAliases(resolveAndInitializeBeanNamesWithAliases(beanFactory), beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves all names (including aliases) from the given Spring {@link BeanFactory}
|
||||
* assigned to the {@link #getAssociatedBeanName()}.
|
||||
*
|
||||
* @param beanFactory {@link BeanFactory} used to resolve the names assigned to the Spring bean
|
||||
* identified by the {@link #getAssociatedBeanName()}.
|
||||
* @return a {@link Set} of all the names assigned to the Spring bean identified by
|
||||
* the {@link #getAssociatedBeanName()} using the provided Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see #getAssociatedBeanName()
|
||||
*/
|
||||
Set<String> resolveAndInitializeBeanNamesWithAliases(BeanFactory beanFactory) {
|
||||
String associatedBeanName = getAssociatedBeanName();
|
||||
|
||||
if (beanFactory != null && StringUtils.hasText(associatedBeanName)) {
|
||||
String[] beanAliases = beanFactory.getAliases(associatedBeanName);
|
||||
|
||||
this.associatedBeanNameWithAliases = new TreeSet<>();
|
||||
this.associatedBeanNameWithAliases.add(associatedBeanName);
|
||||
|
||||
Collections.addAll(this.associatedBeanNameWithAliases, beanAliases);
|
||||
}
|
||||
|
||||
return this.associatedBeanNameWithAliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
unregisterAliases(getAssociatedBeanNameWithAliases());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to use a single, existing Spring {@link BeanFactory} from the registry based on
|
||||
* the {@link #setBeanName(String)} beanName} property.
|
||||
*
|
||||
* @return the single Spring {@link BeanFactory} from the registry.
|
||||
* @throws IllegalStateException if the {@link BeanFactory} with the associated
|
||||
* {@link #setBeanName(String) beanName} is not found.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see #getAssociatedBeanName()
|
||||
* @see #useBeanFactory(String)
|
||||
*/
|
||||
public BeanFactory useBeanFactory() {
|
||||
return useBeanFactory(getAssociatedBeanName());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param beanFactoryKey
|
||||
* @return
|
||||
*/
|
||||
public BeanFactory useBeanFactory(String beanFactoryKey) {
|
||||
return newBeanFactoryReference(StringUtils.hasText(beanFactoryKey) ? resolveBeanFactory(beanFactoryKey)
|
||||
: resolveSingleBeanFactory()).get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link BeanFactory} managed by this {@link GemfireBeanFactoryLocator} instance;
|
||||
* Might be {@literal null} if this {@link GemfireBeanFactoryLocator} is just used to lookup
|
||||
* an existing {@link BeanFactory} reference.
|
||||
*
|
||||
* @return the managed {@link BeanFactory} reference.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.associatedBeanName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the Spring bean associated with the Spring {@link BeanFactory} that possibly created the bean.
|
||||
*
|
||||
* @return a {@link String} containing the name of the Spring bean associated with the Spring {@link BeanFactory}.
|
||||
* @see #setBeanFactory(BeanFactory)
|
||||
*/
|
||||
protected String getAssociatedBeanName() {
|
||||
return this.associatedBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} of all names and aliases assigned to the Spring bean that is associated with
|
||||
* the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @return a {@link Set} containing all the names and aliases assigned to the Spring bean associated with
|
||||
* the Spring {@link BeanFactory}.
|
||||
* @see #setBeanName(String)
|
||||
*/
|
||||
protected Set<String> getAssociatedBeanNameWithAliases() {
|
||||
return Collections.unmodifiableSet(nullSafeSet(this.associatedBeanNameWithAliases));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method to set the bean name used by this locator to lookup a Spring {@link BeanFactory}.
|
||||
*
|
||||
* @param beanName {@link String} containing the bean name to set on this locator.
|
||||
* @return this {@link GemfireBeanFactoryLocator}.
|
||||
* @see #setBeanName(String)
|
||||
*/
|
||||
public GemfireBeanFactoryLocator withBeanName(String beanName) {
|
||||
setBeanName(beanName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference holder storing a reference to a Spring {@link BeanFactory}.
|
||||
*
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected static class BeanFactoryReference {
|
||||
|
||||
protected static final String UNINITIALIZED_BEAN_FACTORY_REFERENCE_MESSAGE =
|
||||
"A BeanFactory was not initialized; Please verify the useBeanFactoryLocator property was properly set";
|
||||
|
||||
private final AtomicReference<BeanFactory> beanFactory = new AtomicReference<>(null);
|
||||
|
||||
/**
|
||||
* Factory method to construct an instance of {@link BeanFactoryReference} initialized
|
||||
* with the given {@link BeanFactory}.
|
||||
*
|
||||
* @param beanFactory {@link BeanFactory} reference to store.
|
||||
* @return a new instance of {@link BeanFactoryReference} initialized with the given {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see #BeanFactoryReference(BeanFactory)
|
||||
*/
|
||||
public static BeanFactoryReference newBeanFactoryReference(BeanFactory beanFactory) {
|
||||
return new BeanFactoryReference(beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link BeanFactoryReference} initialized with the given {@link BeanFactory}.
|
||||
*
|
||||
* @param beanFactory {@link BeanFactory} reference to store; may be {@literal null}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
public BeanFactoryReference(BeanFactory beanFactory) {
|
||||
this.beanFactory.set(beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference to the Spring {@link BeanFactory}.
|
||||
*
|
||||
* @return a reference to the Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
public BeanFactory get() {
|
||||
BeanFactory beanFactory = this.beanFactory.get();
|
||||
|
||||
Assert.state(beanFactory != null, UNINITIALIZED_BEAN_FACTORY_REFERENCE_MESSAGE);
|
||||
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the stored reference to the Spring {@link BeanFactory}.
|
||||
*/
|
||||
public void release() {
|
||||
this.beanFactory.set(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire.support;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.geode.cache.CacheCallback;
|
||||
import org.apache.geode.cache.CacheLoader;
|
||||
import org.apache.geode.cache.Declarable;
|
||||
import org.apache.geode.cache.LoaderHelper;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The {@link LazyWiringDeclarableSupport} class is an implementation of GemFire's {@link Declarable} interface
|
||||
* that enables support for wiring GemFire components with Spring bean dependencies defined in
|
||||
* a Spring {@link ApplicationContext}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
* @see org.springframework.context.ApplicationListener
|
||||
* @see org.springframework.context.event.ContextRefreshedEvent
|
||||
* @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer
|
||||
* @see org.springframework.data.gemfire.support.WiringDeclarableSupport
|
||||
* @see org.apache.geode.cache.Declarable
|
||||
* @since 1.3.4
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class LazyWiringDeclarableSupport extends WiringDeclarableSupport
|
||||
implements ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
|
||||
// atomic reference to the parameters passed by GemFire when this Declarable object
|
||||
// was constructed, configured and its init method called
|
||||
private final AtomicReference<Properties> parametersReference = new AtomicReference<>();
|
||||
|
||||
// condition to determine the initialized state of this Declarable object
|
||||
volatile boolean initialized = false;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@link LazyWiringDeclarableSupport} class registered with the
|
||||
* {@link SpringContextBootstrappingInitializer} as a Spring {@link ApplicationListener}.
|
||||
*
|
||||
* This {@link Declarable} object will receive notifications from the {@link SpringContextBootstrappingInitializer}
|
||||
* when the Spring context is created and initialized (refreshed). The notification is necessary in order for
|
||||
* this {@link Declarable} object to be properly configured and initialized with any required,
|
||||
* Spring-defined dependencies.
|
||||
*
|
||||
* @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer
|
||||
* #register(org.springframework.context.ApplicationListener)
|
||||
*/
|
||||
public LazyWiringDeclarableSupport() {
|
||||
SpringContextBootstrappingInitializer.register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that this {@link Declarable} object has been properly configured and initialized by the Spring container
|
||||
* after has GemFire constructed this {@link Declarable} object during startup.
|
||||
*
|
||||
* This method is recommended to be called before any of this {@link Declarable} object's {@link CacheCallback}
|
||||
* methods (e.g. {@link CacheLoader#load(LoaderHelper)} are invoked in order to ensure that this {@link Declarable}
|
||||
* object was properly constructed, configured and initialized by the Spring container before hand.
|
||||
*
|
||||
* @throws IllegalStateException if this {@link Declarable} object was not been properly constructed, configured
|
||||
* and initialized by the Spring container.
|
||||
* @see #init(java.util.Properties)
|
||||
* @see #isInitialized()
|
||||
*/
|
||||
protected void assertInitialized() {
|
||||
Assert.state(isInitialized(), String.format(
|
||||
"This Declarable object [%s] has not been properly configured and initialized", getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that this {@link Declarable} object has not yet been used, or activated prior to being fully constructed,
|
||||
* configured and initialized by the Spring container.
|
||||
*
|
||||
* It is possible, though rare, that the {@link #init(Properties)} method might be called multiple times by GemFire
|
||||
* before the Spring container constructs, configures, initializes and generally puts this component to use.
|
||||
*
|
||||
* @throws java.lang.IllegalStateException if the Declarable object has already been configured and initialized
|
||||
* by the Spring container.
|
||||
* @see #init(java.util.Properties)
|
||||
* @see #isNotInitialized()
|
||||
*/
|
||||
protected void assertUninitialized() {
|
||||
Assert.state(isNotInitialized(), String.format(
|
||||
"This Declarable object [%s] has already been configured and initialized", getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this {@link Declarable} object has been properly configured and initialized
|
||||
* by the Spring container.
|
||||
*
|
||||
* @return a boolean value indicating whether this {@link Declarable} object has been properly configured
|
||||
* and initialized by the Spring container.
|
||||
* @see #doInit(Properties)
|
||||
* @see #assertInitialized()
|
||||
*/
|
||||
protected boolean isInitialized() {
|
||||
return this.initialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this {@link Declarable} object has been properly configured and initialized
|
||||
* by the Spring container.
|
||||
*
|
||||
* @return a boolean value indicating whether this {@link Declarable} object has been properly configured
|
||||
* and initialized by the Spring container.
|
||||
* @see #doInit(Properties)
|
||||
* @see #isInitialized()
|
||||
*/
|
||||
protected boolean isNotInitialized() {
|
||||
return !isInitialized();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization method called by GemFire with the configured parameters once this {@link Declarable} object
|
||||
* has been constructed by GemFire and the <initalizer> element is parsed
|
||||
* in GemFire's configuration meta-data during startup.
|
||||
*
|
||||
* @param parameters {@link Properties} containing the configured parameters parsed from GemFire's
|
||||
* configuration meta-data (e.g. {@literal cache.xml}) and passed to this {@link Declarable} object.
|
||||
* @see #doInit(Properties)
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
@Override
|
||||
public final void init(Properties parameters) {
|
||||
setParameters(parameters);
|
||||
|
||||
try {
|
||||
doInit(locateBeanFactory(), nullSafeGetParameters());
|
||||
}
|
||||
catch (IllegalStateException ignore) {
|
||||
// BeanFactory does not exist, has been closed or the GemfireBeanFactoryLocator is not in use
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual configuration and initialization of this {@link Declarable} object before use.
|
||||
*
|
||||
* This method is triggered by the Spring {@link org.springframework.context.ApplicationContext}, Spring application
|
||||
* {@link ContextRefreshedEvent}) indicating that the Spring container (context) has been created and refreshed.
|
||||
*
|
||||
* @param parameters {@link Properties} containing the configured parameters parsed from GemFire's
|
||||
* configuration meta-data (e.g. {@literal cache.xml}) and passed to this {@link Declarable} object.
|
||||
* @throws IllegalArgumentException if the {@literal bean-name} parameter was specified in GemFire's
|
||||
* configuration meta-data but no bean with the specified name could be found in the Spring context.
|
||||
* @see #init(java.util.Properties)
|
||||
* @see #configureThis(BeanFactory, String)
|
||||
* @see #doPostInit(java.util.Properties)
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
synchronized void doInit(BeanFactory beanFactory, Properties parameters) {
|
||||
this.initialized = (isInitialized() || configureThis(beanFactory,
|
||||
parameters.getProperty(TEMPLATE_BEAN_NAME_PROPERTY)));
|
||||
|
||||
doPostInit(parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs any post configuration and initialization activities required by the application.
|
||||
*
|
||||
* By default, this method does nothing.
|
||||
*
|
||||
* @param parameters {@link Properties} containing the configured parameters parsed from GemFire's
|
||||
* configuration meta-data (e.g. {@literal cache.xml}) and passed to this {@link Declarable} object.
|
||||
* @see #doInit(Properties)
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
protected void doPostInit(Properties parameters) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation to return the parameters passed to this {@link Declarable} object when created by GemFire
|
||||
* from it's own configuration meta-data (e.g. {@literal cache.xml}).
|
||||
*
|
||||
* @return a {@link Properties} containing the configured parameters parsed from GemFire's configuration meta-data
|
||||
* (e.g. {@literal cache.xml}) and passed to this {@link Declarable} object.
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
protected Properties nullSafeGetParameters() {
|
||||
Properties parameters = parametersReference.get();
|
||||
return (parameters != null ? parameters : new Properties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a reference to the {@link Properties parameters} passed to the {@link Declarable#init(Properties)} method.
|
||||
*
|
||||
* @param parameters {@link Properties} containing the configured parameters parsed from GemFire's
|
||||
* configuration meta-data (e.g. {@literal cache.xml}) and passed to this {@link Declarable} object.
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
protected void setParameters(Properties parameters) {
|
||||
parametersReference.set(parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler method called when GemFire has created and initialized (refreshed)
|
||||
* the Spring {@link ApplicationContext} using the {@link SpringContextBootstrappingInitializer}.
|
||||
*
|
||||
* @param event {@link ContextRefreshedEvent} published by the Spring {@link ApplicationContext} after it is
|
||||
* successfully created and initialized by GemFire.
|
||||
* @see org.springframework.context.event.ContextRefreshedEvent
|
||||
* @see #doInit(BeanFactory, Properties)
|
||||
* @see #nullSafeGetParameters()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public final void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
ApplicationContext applicationContext = event.getApplicationContext();
|
||||
|
||||
Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext, String.format(
|
||||
"The Spring ApplicationContext [%s] must be an instance of ConfigurableApplicationContext",
|
||||
applicationContext));
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory =
|
||||
((ConfigurableApplicationContext) applicationContext).getBeanFactory();
|
||||
|
||||
doInit(beanFactory, nullSafeGetParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* When this {@link Declarable} object/bean gets destroyed by the Spring container, {@code destroy()} will
|
||||
* make sure this component gets unregistered from the {@link SpringContextBootstrappingInitializer} properly.
|
||||
*
|
||||
* @throws Exception if bean destruction is unsuccessful.
|
||||
* @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer
|
||||
* #unregister(org.springframework.context.ApplicationListener)
|
||||
* @see #setParameters(Properties)
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
SpringContextBootstrappingInitializer.unregister(this);
|
||||
setParameters(null);
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.Declarable;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
@@ -44,11 +45,11 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The SpringContextBootstrappingInitializer class is a GemFire configuration initializer used to bootstrap a Spring
|
||||
* ApplicationContext inside a GemFire Server JVM-based process. This enables a GemFire Cache Server resources to be
|
||||
* mostly configured with Spring Data GemFire's XML namespace. The Cache itself is the only resource that cannot be
|
||||
* configured and initialized in a Spring context since the initializer is not invoked until after GemFire creates
|
||||
* and initializes the Cache for use.
|
||||
* The {@link SpringContextBootstrappingInitializer} class is a GemFire configuration initializer used to bootstrap
|
||||
* a Spring {@link ApplicationContext} inside a GemFire Server JVM-based process. This enables a GemFire Server
|
||||
* resource to be mostly configured with Spring Data GemFire's configuration meta-data. The GemFire {@link Cache}
|
||||
* itself is the only resource that cannot be configured and initialized in a Spring context since the initializer
|
||||
* is not invoked until after GemFire creates and initializes the GemFire {@link Cache} for use.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.context.ApplicationContext
|
||||
@@ -58,6 +59,8 @@ import org.springframework.util.StringUtils;
|
||||
* @see org.springframework.context.event.ApplicationContextEvent
|
||||
* @see org.springframework.context.event.ApplicationEventMulticaster
|
||||
* @see org.springframework.context.support.ClassPathXmlApplicationContext
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
* @see org.apache.geode.cache.Cache
|
||||
* @see org.apache.geode.cache.Declarable
|
||||
* @link http://gemfire.docs.pivotal.io/latest/userguide/index.html#basic_config/the_cache/setting_cache_initializer.html
|
||||
* @link https://jira.springsource.org/browse/SGF-248
|
||||
@@ -74,13 +77,13 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
|
||||
private static final ApplicationEventMulticaster applicationEventNotifier = new SimpleApplicationEventMulticaster();
|
||||
|
||||
private static final AtomicReference<ClassLoader> beanClassLoaderReference = new AtomicReference<ClassLoader>(null);
|
||||
private static final AtomicReference<ClassLoader> beanClassLoaderReference = new AtomicReference<>(null);
|
||||
|
||||
static volatile ConfigurableApplicationContext applicationContext;
|
||||
|
||||
static volatile ContextRefreshedEvent contextRefreshedEvent;
|
||||
|
||||
private static final List<Class<?>> registeredAnnotatedClasses = new CopyOnWriteArrayList<Class<?>>();
|
||||
private static final List<Class<?>> registeredAnnotatedClasses = new CopyOnWriteArrayList<>();
|
||||
|
||||
protected final Log logger = initLogger();
|
||||
|
||||
@@ -92,7 +95,9 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
* @see org.springframework.context.ConfigurableApplicationContext
|
||||
*/
|
||||
public static synchronized ConfigurableApplicationContext getApplicationContext() {
|
||||
Assert.state(applicationContext != null, "The Spring ApplicationContext was not configured and initialized properly!");
|
||||
Assert.state(applicationContext != null,
|
||||
"A Spring ApplicationContext was not configured and initialized properly");
|
||||
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
@@ -110,7 +115,7 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
beanClassLoaderReference.set(beanClassLoader);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("The Spring ApplicationContext has already been initialized!");
|
||||
throw new IllegalStateException("A Spring ApplicationContext has already been initialized");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,8 +259,11 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
"'AnnotatedClasses', 'basePackages' or 'configLocations' must be specified in order to"
|
||||
+ " construct and configure an instance of the ConfigurableApplicationContext");
|
||||
|
||||
Class<?>[] annotatedClasses = registeredAnnotatedClasses.toArray(
|
||||
new Class<?>[registeredAnnotatedClasses.size()]);
|
||||
|
||||
return scanBasePackages(registerAnnotatedClasses(createApplicationContext(configLocations),
|
||||
registeredAnnotatedClasses.toArray(new Class<?>[registeredAnnotatedClasses.size()])), basePackages);
|
||||
annotatedClasses), basePackages);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) - used for testing purposes only */
|
||||
@@ -276,9 +284,11 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
* @throws java.lang.IllegalArgumentException if the ApplicationContext reference is null!
|
||||
*/
|
||||
protected ConfigurableApplicationContext initApplicationContext(ConfigurableApplicationContext applicationContext) {
|
||||
Assert.notNull(applicationContext, "The ConfigurableApplicationContext reference must not be null");
|
||||
Assert.notNull(applicationContext, "ConfigurableApplicationContext must not be null");
|
||||
|
||||
applicationContext.addApplicationListener(this);
|
||||
applicationContext.registerShutdownHook();
|
||||
|
||||
return setClassLoader(applicationContext);
|
||||
}
|
||||
|
||||
@@ -292,8 +302,10 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
* @throws java.lang.IllegalArgumentException if the ApplicationContext reference is null!
|
||||
*/
|
||||
protected ConfigurableApplicationContext refreshApplicationContext(ConfigurableApplicationContext applicationContext) {
|
||||
Assert.notNull(applicationContext, "The ConfigurableApplicationContext reference must not be null");
|
||||
Assert.notNull(applicationContext, "ConfigurableApplicationContext must not be null");
|
||||
|
||||
applicationContext.refresh();
|
||||
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
@@ -310,7 +322,10 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
*/
|
||||
ConfigurableApplicationContext registerAnnotatedClasses(ConfigurableApplicationContext applicationContext,
|
||||
Class<?>[] annotatedClasses) {
|
||||
if (applicationContext instanceof AnnotationConfigApplicationContext && !ObjectUtils.isEmpty(annotatedClasses)) {
|
||||
|
||||
if (applicationContext instanceof AnnotationConfigApplicationContext
|
||||
&& !ObjectUtils.isEmpty(annotatedClasses)) {
|
||||
|
||||
((AnnotationConfigApplicationContext) applicationContext).register(annotatedClasses);
|
||||
}
|
||||
|
||||
@@ -329,7 +344,10 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
*/
|
||||
ConfigurableApplicationContext scanBasePackages(ConfigurableApplicationContext applicationContext,
|
||||
String[] basePackages) {
|
||||
if (applicationContext instanceof AnnotationConfigApplicationContext && !ObjectUtils.isEmpty(basePackages)) {
|
||||
|
||||
if (applicationContext instanceof AnnotationConfigApplicationContext
|
||||
&& !ObjectUtils.isEmpty(basePackages)) {
|
||||
|
||||
((AnnotationConfigApplicationContext) applicationContext).scan(basePackages);
|
||||
}
|
||||
|
||||
@@ -354,17 +372,6 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation used to get the ID of the Spring ApplicationContext.
|
||||
*
|
||||
* @param applicationContext the Spring ApplicationContext from which to get the ID.
|
||||
* @return the ID of the given Spring ApplicationContext or null if the ApplicationContext reference is null.
|
||||
* @see org.springframework.context.ApplicationContext#getId()
|
||||
*/
|
||||
String nullSafeGetApplicationContextId(ApplicationContext applicationContext) {
|
||||
return (applicationContext != null ? applicationContext.getId() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a Spring ApplicationContext with the given parameters specified with a GemFire <initializer>
|
||||
* block in cache.xml.
|
||||
@@ -380,7 +387,7 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
@Override
|
||||
public void init(final Properties parameters) {
|
||||
public void init(Properties parameters) {
|
||||
try {
|
||||
synchronized (SpringContextBootstrappingInitializer.class) {
|
||||
if (applicationContext == null || !applicationContext.isActive()) {
|
||||
@@ -412,6 +419,17 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe operation used to get the ID of the Spring ApplicationContext.
|
||||
*
|
||||
* @param applicationContext the Spring ApplicationContext from which to get the ID.
|
||||
* @return the ID of the given Spring ApplicationContext or null if the ApplicationContext reference is null.
|
||||
* @see org.springframework.context.ApplicationContext#getId()
|
||||
*/
|
||||
String nullSafeGetApplicationContextId(ApplicationContext applicationContext) {
|
||||
return (applicationContext != null ? applicationContext.getId() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets notified when the Spring ApplicationContext gets created and refreshed by GemFire, once the
|
||||
* <initializer> block is processed and the SpringContextBootstrappingInitializer Declarable component
|
||||
@@ -429,7 +447,7 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
* #multicastEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(final ApplicationContextEvent event) {
|
||||
public void onApplicationEvent(ApplicationContextEvent event) {
|
||||
if (event instanceof ContextRefreshedEvent) {
|
||||
synchronized (applicationEventNotifier) {
|
||||
contextRefreshedEvent = (ContextRefreshedEvent) event;
|
||||
@@ -442,5 +460,4 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed 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 org.springframework.data.gemfire.support;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.geode.cache.Declarable;
|
||||
import org.apache.shiro.util.Assert;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
import org.springframework.beans.factory.wiring.BeanWiringInfo;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link Declarable} support class used to wire declaring, implementing instances through the Spring container.
|
||||
*
|
||||
* This implementation first looks for a {@literal 'bean-name'} property, which will be used to locate
|
||||
* a Spring bean definition used as the 'template' for auto-wiring purposes. Auto-wiring will be performed
|
||||
* based on the settings defined in the Spring container.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.beans.factory.wiring.BeanWiringInfo
|
||||
* @see DeclarableSupport
|
||||
* @see LazyWiringDeclarableSupport
|
||||
* @see org.apache.geode.cache.Declarable
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class WiringDeclarableSupport extends DeclarableSupport {
|
||||
|
||||
protected static final String TEMPLATE_BEAN_NAME_PROPERTY = "bean-name";
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void init(Properties parameters) {
|
||||
configureThis(parameters.getProperty(TEMPLATE_BEAN_NAME_PROPERTY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this {@link Declarable} object using the bean defined and identified in the Spring {@link BeanFactory}
|
||||
* with the given {@code name} used as a template for auto-wiring purposes.
|
||||
*
|
||||
* @param templateBeanName {@link String} containing the name of the Spring bean used as a template
|
||||
* for auto-wiring purposes.
|
||||
* @return a boolean value indicating whether this {@link Declarable} object was successfully configured
|
||||
* and initialized by the Spring container.
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see #configureThis(BeanFactory, String)
|
||||
* @see #locateBeanFactory()
|
||||
*/
|
||||
protected boolean configureThis(String templateBeanName) {
|
||||
return configureThis(locateBeanFactory(), templateBeanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this {@link Declarable} object using the bean defined and identified in the given
|
||||
* Spring {@link BeanFactory} with the given {@code name} used as a template for auto-wiring purposes.
|
||||
*
|
||||
* @param beanFactory Spring {@link BeanFactory} used to configure, auto-wire
|
||||
* and initialize this {@link Declarable} object.
|
||||
* @param templateBeanName {@link String} containing the name of the Spring bean used as a template
|
||||
* for auto-wiring purposes.
|
||||
* @return a boolean value indicating whether this {@link Declarable} object was successfully configured
|
||||
* and initialized by the Spring container.
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see #newBeanConfigurer(BeanFactory, String)
|
||||
*/
|
||||
protected boolean configureThis(BeanFactory beanFactory, String templateBeanName) {
|
||||
BeanConfigurerSupport beanConfigurer = newBeanConfigurer(beanFactory, templateBeanName);
|
||||
|
||||
beanConfigurer.configureBean(this);
|
||||
beanConfigurer.destroy();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, initialized instance of {@link BeanConfigurerSupport} configured with
|
||||
* the given Spring {@link BeanFactory}.
|
||||
*
|
||||
* @param beanFactory reference to the Spring {@link BeanFactory}.
|
||||
* @return a new, initialized instance of {@link BeanConfigurerSupport} configured with
|
||||
* the given Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see #newBeanConfigurer(BeanFactory, String)
|
||||
*/
|
||||
protected BeanConfigurerSupport newBeanConfigurer(BeanFactory beanFactory) {
|
||||
return newBeanConfigurer(beanFactory, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, initialized instance of {@link BeanConfigurerSupport} configured with
|
||||
* the given Spring {@link BeanFactory} and name of a Spring bean defined in the Spring {@link BeanFactory}
|
||||
* used as a template to wire this {@link Declarable} object.
|
||||
*
|
||||
* @param beanFactory reference to the Spring {@link BeanFactory}.
|
||||
* @param templateBeanName {@link String} containing the name of a Spring bean in the Spring {@link BeanFactory}
|
||||
* used as a template to wire this {@link Declarable} object.
|
||||
* @return a new, initialized instance of {@link BeanConfigurerSupport} configured with
|
||||
* the given Spring {@link BeanFactory}.
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanConfigurerSupport newBeanConfigurer(BeanFactory beanFactory, String templateBeanName) {
|
||||
BeanConfigurerSupport beanConfigurer = new BeanConfigurerSupport();
|
||||
|
||||
beanConfigurer.setBeanFactory(beanFactory);
|
||||
|
||||
if (StringUtils.hasText(templateBeanName)) {
|
||||
Assert.isTrue(beanFactory.containsBean(templateBeanName),
|
||||
String.format("Cannot find bean with name [%s]", templateBeanName));
|
||||
|
||||
beanConfigurer.setBeanWiringInfoResolver(beanInstance -> new BeanWiringInfo(templateBeanName));
|
||||
}
|
||||
|
||||
beanConfigurer.afterPropertiesSet();
|
||||
|
||||
return beanConfigurer;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,16 @@ public abstract class SpringUtils {
|
||||
return (obj1 == null ? obj2 == null : obj1.equals(obj2));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static boolean nullOrEquals(Object obj1, Object obj2) {
|
||||
return (obj1 == null || obj1.equals(obj2));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static boolean nullSafeEquals(Object obj1, Object obj2) {
|
||||
return (obj1 != null && obj1.equals(obj2));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static String dereferenceBean(String beanName) {
|
||||
return String.format("%1$s%2$s", BeanFactory.FACTORY_BEAN_PREFIX, beanName);
|
||||
|
||||
Reference in New Issue
Block a user