DATAGEODE-219 - Invoke SmartLifecycle callbacks when defining Regions based on Caching annotations.

This commit is contained in:
John Blum
2019-08-16 00:41:29 -07:00
parent 715cbb2e9e
commit 2a7e9d28db
6 changed files with 454 additions and 12 deletions

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException;
@@ -23,6 +22,7 @@ import java.util.Optional;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Region;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
@@ -204,7 +204,6 @@ public abstract class ResolvableRegionFactoryBean<K, V> extends AbstractFactoryB
}
/**
>>>>>>> DATAGEODE-95 - Upgrade to Apache Geode 1.5.0.
* Returns a reference to the {@link GemFireCache} used to create the {@link Region}.
*
* @return a reference to the {@link GemFireCache} used to create the {@link Region}..

View File

@@ -54,6 +54,7 @@ import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.Lifecycle;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
@@ -62,6 +63,7 @@ import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
import org.springframework.data.gemfire.config.annotation.support.CacheTypeAwareRegionFactoryBean;
import org.springframework.data.gemfire.support.CompositeLifecycle;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
@@ -114,6 +116,8 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
private ClientRegionShortcut clientRegionShortcut = ClientRegionShortcut.PROXY;
private CompositeLifecycle compositeLifecycle = new CompositeLifecycle();
@Autowired(required = false)
private List<RegionConfigurer> regionConfigurers = Collections.emptyList();
@@ -277,7 +281,6 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
}
@Bean
@SuppressWarnings("all")
public BeanPostProcessor cachingAnnotationsRegionBeanRegistrar(ConfigurableBeanFactory beanFactory) {
return new BeanPostProcessor() {
@@ -319,6 +322,8 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
regionFactoryBean.afterPropertiesSet();
this.compositeLifecycle.add(regionFactoryBean);
Optional.ofNullable(regionFactoryBean.getObject())
.ifPresent(region -> beanFactory.registerSingleton(cacheName, region));
}
@@ -332,7 +337,7 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
return beanFactory;
}
protected List<RegionConfigurer> resolveRegionConfigurers() {
private List<RegionConfigurer> resolveRegionConfigurers() {
return Optional.ofNullable(this.regionConfigurers)
.filter(regionConfigurers -> !regionConfigurers.isEmpty())
@@ -340,6 +345,11 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
Collections.singletonList(LazyResolvingComposableRegionConfigurer.create(getBeanFactory())));
}
@Bean
public Lifecycle cachingDefinedRegionsCompositeLifecycleBean() {
return this.compositeLifecycle;
}
/**
* {@link CacheNameResolver} is a {@link FunctionalInterface} declaring a contract for all implementations
* used to resolve all cache names declared and used by a Spring application. A resolver typically inspects
@@ -373,14 +383,13 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
protected abstract Class<? extends Annotation>[] getMethodCacheAnnotationTypes();
@SuppressWarnings("unchecked")
protected Class[] append(Class[] annotationTypes, Class... additionalAnnotationTypes) {
List<Class> annotationTypeList = new ArrayList<>(Arrays.asList(annotationTypes));
Collections.addAll(annotationTypeList, additionalAnnotationTypes);
return annotationTypeList.toArray(new Class[annotationTypeList.size()]);
return annotationTypeList.toArray(new Class[0]);
}
protected Set<String> resolveCacheNames(Annotation annotation) {
@@ -402,12 +411,9 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
}
@Override
@SuppressWarnings("unchecked")
public Set<String> resolveCacheNames(Class<?> type) {
Set<String> cacheNames = new HashSet<>();
cacheNames.addAll(resolveCacheNames(type, getClassCacheAnnotationTypes()));
Set<String> cacheNames = new HashSet<>(resolveCacheNames(type, getClassCacheAnnotationTypes()));
stream(type.getMethods())
.filter(method -> isUserLevelMethod(method))
@@ -457,7 +463,6 @@ public class CachingDefinedRegionsConfiguration extends AbstractAnnotationConfig
}
@Override
@SuppressWarnings("unchecked")
public Set<String> resolveCacheNames(Class<?> type) {
Set<String> cacheNames = super.resolveCacheNames(type);

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2019 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
*
* https://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.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.springframework.context.Lifecycle;
import org.springframework.context.SmartLifecycle;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
/**
* A Spring {@link Lifecycle} that implements the {@literal Composite software design pattern} composing 1 or more
* {@link Lifecycle} components as a single, logical, composite {@link Lifecycle} object.
*
* @author John Blum
* @see java.lang.Iterable
* @see org.springframework.context.Lifecycle
* @see org.springframework.context.SmartLifecycle
* @since 2.2.0
*/
@SuppressWarnings("unused")
public final class CompositeLifecycle implements Iterable<Lifecycle>, SmartLifecycle {
private final List<Lifecycle> lifecycleComponents = new CopyOnWriteArrayList<>();
/**
* Adds a {@link Lifecycle} object to this composite.
*
* @param lifecycleComponent {@link Lifecycle} object to add to this composite.
* @return a boolean value if the {@link Lifecycle} object is not {@literal null}
* and was successfully added to this composite.
* @see #remove(Lifecycle)
*/
@SuppressWarnings("all")
public boolean add(@NonNull Lifecycle lifecycleComponent) {
return lifecycleComponent != null && this.lifecycleComponents.add(lifecycleComponent);
}
/**
* Returns a boolean value indicating whether this composite contains any {@link Lifecycle} objects.
*
* @return a boolean value indicating whether this composite contains any {@link Lifecycle} objects.
*/
public boolean isEmpty() {
return this.lifecycleComponents.isEmpty();
}
/**
* Returns an {@link Iterator} over the {@link Lifecycle} objects contained by this composite.
*
* @return an {@link Iterator} over the {@link Lifecycle} objects contained by this composite.
* @see java.util.Iterator
*/
@Override
public Iterator<Lifecycle> iterator() {
return Collections.unmodifiableList(this.lifecycleComponents).iterator();
}
/**
* Removes the given {@link Lifecycle} object from this composite.
*
* @param lifecycleComponent {@link Lifecycle} object to remove.
* @return a boolean if the {@link Lifecycle} object was part of this composite
* and was able to be removed successfully.
* @see #add(Lifecycle)
*/
public boolean remove(@Nullable Lifecycle lifecycleComponent) {
return this.lifecycleComponents.remove(lifecycleComponent);
}
/**
* Returns the number of {@link Lifecycle} objects contained by this composite.
*
* @return an integer value specifying the number of {@link Lifecycle} objects contained by this composite.
*/
public int size() {
return this.lifecycleComponents.size();
}
/**
* Determines whether any {@link Lifecycle} object contained by this composite is running.
*
* @return a boolean value indicating whether any {@link Lifecycle} object
* contained by this composite is running.
* @see org.springframework.context.Lifecycle#isRunning()
*/
@Override
public boolean isRunning() {
for (Lifecycle lifecycleComponent : this) {
if (lifecycleComponent.isRunning()) {
return true;
}
}
return false;
}
/**
* Starts all {@link Lifecycle} objects contained by this composite.
*
* @see #stop()
*/
@Override
public void start() {
this.lifecycleComponents.forEach(Lifecycle::start);
}
/**
* Stops all {@link Lifecycle} objects contained by this composite.
*
* @see #start()
*/
@Override
public void stop() {
this.lifecycleComponents.forEach(Lifecycle::stop);
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.support;
import org.springframework.context.SmartLifecycle;