Merge branch 'redisson/master'
commit
ba4747ec9c
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by jribble on 2/20/17.
|
||||||
|
*/
|
||||||
|
public interface CachedValue<K, V> {
|
||||||
|
boolean isExpired();
|
||||||
|
|
||||||
|
K getKey();
|
||||||
|
|
||||||
|
V getValue();
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.cache;
|
||||||
|
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
|
|
||||||
|
public class CachedValueReference<V> extends SoftReference<V> {
|
||||||
|
|
||||||
|
private final CachedValue<?, ?> owner;
|
||||||
|
|
||||||
|
public CachedValueReference(CachedValue<?, ?> owner, V referent, ReferenceQueue<? super V> q) {
|
||||||
|
super(referent, q);
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CachedValue<?, ?> getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.cache;
|
||||||
|
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Nikita Koksharov
|
||||||
|
*
|
||||||
|
* @param <K> key
|
||||||
|
* @param <V> value
|
||||||
|
*/
|
||||||
|
public class SoftCacheMap<K, V> extends AbstractCacheMap<K, V> {
|
||||||
|
|
||||||
|
private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
|
||||||
|
|
||||||
|
public SoftCacheMap(long timeToLiveInMillis, long maxIdleInMillis) {
|
||||||
|
super(0, timeToLiveInMillis, maxIdleInMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CachedValue<K, V> create(K key, V value, long ttl, long maxIdleTime) {
|
||||||
|
return new SoftCachedValue<K, V>(key, value, ttl, maxIdleTime, queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean removeExpiredEntries() {
|
||||||
|
while (true) {
|
||||||
|
CachedValueReference<V> value = (CachedValueReference<V>) queue.poll();
|
||||||
|
if (value == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
map.remove(value.getOwner().getKey(), value.getOwner());
|
||||||
|
}
|
||||||
|
return super.removeExpiredEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMapFull() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.cache;
|
||||||
|
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by jribble on 2/20/17.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SoftCachedValue<K, V> extends StdCachedValue<K, V> implements CachedValue<K, V> {
|
||||||
|
|
||||||
|
private final CachedValueReference<V> ref;
|
||||||
|
|
||||||
|
public SoftCachedValue(K key, V value, long ttl, long maxIdleTime, ReferenceQueue<V> queue) {
|
||||||
|
super(key, null, ttl, maxIdleTime);
|
||||||
|
this.ref = new CachedValueReference<V>(this, value, queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V getValue() {
|
||||||
|
super.getValue();
|
||||||
|
return ref.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by jribble on 2/20/17.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class StdCachedValue<K, V> implements CachedValue<K, V> {
|
||||||
|
|
||||||
|
protected final K key;
|
||||||
|
protected final V value;
|
||||||
|
|
||||||
|
long ttl;
|
||||||
|
long maxIdleTime;
|
||||||
|
|
||||||
|
long creationTime;
|
||||||
|
long lastAccess;
|
||||||
|
|
||||||
|
public StdCachedValue(K key, V value, long ttl, long maxIdleTime) {
|
||||||
|
this.value = value;
|
||||||
|
this.ttl = ttl;
|
||||||
|
this.key = key;
|
||||||
|
this.maxIdleTime = maxIdleTime;
|
||||||
|
creationTime = System.currentTimeMillis();
|
||||||
|
lastAccess = creationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExpired() {
|
||||||
|
boolean result = false;
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if (ttl != 0 && creationTime + ttl < currentTime) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
if (maxIdleTime != 0 && lastAccess + maxIdleTime < currentTime) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public K getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V getValue() {
|
||||||
|
lastAccess = System.currentTimeMillis();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CachedValue [key=" + key + ", value=" + value + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Nikita Koksharov
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum SubscriptionMode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to slave nodes
|
||||||
|
*/
|
||||||
|
SLAVE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to master node
|
||||||
|
*/
|
||||||
|
MASTER
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.connection;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.redisson.api.RFuture;
|
||||||
|
import org.redisson.misc.RPromise;
|
||||||
|
import org.redisson.misc.RedissonPromise;
|
||||||
|
|
||||||
|
import io.netty.util.concurrent.Future;
|
||||||
|
import io.netty.util.concurrent.FutureListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Nikita Koksharov
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CountListener implements FutureListener<Void> {
|
||||||
|
|
||||||
|
private final RPromise<Void> res;
|
||||||
|
|
||||||
|
private final AtomicInteger counter;
|
||||||
|
|
||||||
|
public static RPromise<Void> create(RFuture<Void>... futures) {
|
||||||
|
RPromise<Void> result = new RedissonPromise<Void>();
|
||||||
|
FutureListener<Void> listener = new CountListener(result, futures.length);
|
||||||
|
for (RFuture<Void> future : futures) {
|
||||||
|
future.addListener(listener);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CountListener(RPromise<Void> res, int amount) {
|
||||||
|
super();
|
||||||
|
this.res = res;
|
||||||
|
this.counter = new AtomicInteger(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void operationComplete(Future<Void> future) throws Exception {
|
||||||
|
if (!future.isSuccess()) {
|
||||||
|
res.tryFailure(future.cause());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (counter.decrementAndGet() == 0) {
|
||||||
|
res.trySuccess(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.misc;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class BeanMethodInvoker extends ArgumentConvertingMethodInvoker
|
||||||
|
implements InitializingBean {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
prepare();
|
||||||
|
try {
|
||||||
|
invoke();
|
||||||
|
} catch (InvocationTargetException ex) {
|
||||||
|
if (ex.getTargetException() instanceof Exception) {
|
||||||
|
throw (Exception) ex.getTargetException();
|
||||||
|
}
|
||||||
|
if (ex.getTargetException() instanceof Error) {
|
||||||
|
throw (Error) ex.getTargetException();
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractRedissonNamespaceDefinitionParser
|
||||||
|
extends AbstractSingleBeanDefinitionParser {
|
||||||
|
|
||||||
|
protected final RedissonNamespaceParserSupport helper;
|
||||||
|
private final RedissonNamespaceDecorator decorator;
|
||||||
|
private final String parentRefAttribute;
|
||||||
|
|
||||||
|
protected AbstractRedissonNamespaceDefinitionParser(RedissonNamespaceParserSupport helper, String parentRefAttribute) {
|
||||||
|
this.helper = helper;
|
||||||
|
this.parentRefAttribute = parentRefAttribute;
|
||||||
|
this.decorator = new RedissonNamespaceDefaultDecorator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractRedissonNamespaceDefinitionParser(RedissonNamespaceParserSupport helper, String parentRefAttribute, RedissonNamespaceDecorator decorator) {
|
||||||
|
this.helper = helper;
|
||||||
|
this.parentRefAttribute = parentRefAttribute;
|
||||||
|
this.decorator = decorator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||||
|
Assert.state(helper.isRedissonNS(element),
|
||||||
|
"Illegal state. "
|
||||||
|
+ this.getClass().getName()
|
||||||
|
+ " can only parse "
|
||||||
|
+ RedissonNamespaceParserSupport.REDISSON_NAMESPACE
|
||||||
|
+ " namespace elements");
|
||||||
|
Assert.state(element.hasAttribute(parentRefAttribute),
|
||||||
|
"Illegal state. property \"" + parentRefAttribute
|
||||||
|
+ "\" is required in the \""
|
||||||
|
+ helper.getName(element)
|
||||||
|
+ "\" element.");
|
||||||
|
|
||||||
|
helper.populateIdAttribute(element, builder, parserContext);
|
||||||
|
AbstractBeanDefinition bd = builder.getRawBeanDefinition();
|
||||||
|
parseNested(element, parserContext, builder, bd);
|
||||||
|
decorator.decorate(element, parserContext, builder, helper);
|
||||||
|
parserContext.getDelegate().parseQualifierElements(element, bd);
|
||||||
|
if (parserContext.isNested()) {
|
||||||
|
helper.registerBeanDefinition(builder, element, parserContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final boolean shouldGenerateIdAsFallback() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.redisson.api.RQueue;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class DelayedQueueDecorator implements RedissonNamespaceDecorator {
|
||||||
|
|
||||||
|
private static final String DESTINATION_QUEUE_REF = "destination-queue-ref";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
Assert.state(element.hasAttribute(DESTINATION_QUEUE_REF),
|
||||||
|
"Illegal state. property \"" + DESTINATION_QUEUE_REF
|
||||||
|
+ "\" is required in the \""
|
||||||
|
+ helper.getName(element)
|
||||||
|
+ "\" element.");
|
||||||
|
helper.addConstructorArgs(new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element, DESTINATION_QUEUE_REF)),
|
||||||
|
RQueue.class, builder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.redisson.api.LocalCachedMapOptions;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.core.Conventions;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class LocalCachedMapOptionsDecorator implements RedissonNamespaceDecorator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
NodeList list = element.getElementsByTagNameNS(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_NAMESPACE,
|
||||||
|
RedissonNamespaceParserSupport.LOCAL_CACHED_MAP_OPTIONS_ELEMENT);
|
||||||
|
Element options = null;
|
||||||
|
String id;
|
||||||
|
if (list.getLength() == 1) {
|
||||||
|
options = (Element) list.item(0);
|
||||||
|
id = invokeOptions(options, parserContext, helper);
|
||||||
|
for (int i = 0; i < options.getAttributes().getLength(); i++) {
|
||||||
|
Attr item = (Attr) options.getAttributes().item(i);
|
||||||
|
if (helper.isEligibleAttribute(item)
|
||||||
|
&& !RedissonNamespaceParserSupport.TIME_TO_LIVE_UNIT_ATTRIBUTE
|
||||||
|
.equals(item.getLocalName())
|
||||||
|
&& !RedissonNamespaceParserSupport.MAX_IDLE_UNIT_ATTRIBUTE
|
||||||
|
.equals(item.getLocalName())) {
|
||||||
|
helper.invoker(id,
|
||||||
|
helper.getName(item),
|
||||||
|
new Object[]{item.getValue()},
|
||||||
|
parserContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
invokeTimeUnitOptions(options, id, parserContext, helper,
|
||||||
|
RedissonNamespaceParserSupport.TIME_TO_LIVE_ATTRIBUTE,
|
||||||
|
RedissonNamespaceParserSupport.TIME_TO_LIVE_UNIT_ATTRIBUTE);
|
||||||
|
|
||||||
|
invokeTimeUnitOptions(options, id, parserContext, helper,
|
||||||
|
RedissonNamespaceParserSupport.MAX_IDLE_ATTRIBUTE,
|
||||||
|
RedissonNamespaceParserSupport.MAX_IDLE_UNIT_ATTRIBUTE);
|
||||||
|
} else {
|
||||||
|
id = invokeOptions(options, parserContext, helper);
|
||||||
|
}
|
||||||
|
helper.addConstructorArgs(new RuntimeBeanReference(id),
|
||||||
|
LocalCachedMapOptions.class, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String invokeOptions(Element element, ParserContext parserContext, RedissonNamespaceParserSupport helper) {
|
||||||
|
BeanComponentDefinition defaultOption
|
||||||
|
= helper.factoryInvoker(element, LocalCachedMapOptions.class,
|
||||||
|
"defaults", null, parserContext);
|
||||||
|
return defaultOption.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invokeTimeUnitOptions(Element element, String id, ParserContext parserContext, RedissonNamespaceParserSupport helper, String timeAttrubute, String timeUnitAttribute) {
|
||||||
|
if (helper.hasAttribute(element, timeUnitAttribute)) {
|
||||||
|
Assert.state(
|
||||||
|
helper.hasAttribute(element, timeAttrubute),
|
||||||
|
"Missing \"" + timeAttrubute + "\" attribute in \""
|
||||||
|
+ RedissonNamespaceParserSupport.LOCAL_CACHED_MAP_OPTIONS_ELEMENT
|
||||||
|
+ "\" element.");
|
||||||
|
helper.invoker(id,
|
||||||
|
Conventions.attributeNameToPropertyName(timeAttrubute),
|
||||||
|
new Object[]{
|
||||||
|
Integer.parseInt(
|
||||||
|
helper.getAttribute(element, timeAttrubute)),
|
||||||
|
helper.getAttribute(element, timeUnitAttribute)},
|
||||||
|
parserContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class ReadWriteLockDecorator implements RedissonNamespaceDecorator {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
parseNested(element, RedissonNamespaceParserSupport.READ_LOCK_ELEMENT, parserContext, builder, helper);
|
||||||
|
parseNested(element, RedissonNamespaceParserSupport.WRITE_LOCK_ELEMENT, parserContext, builder, helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseNested(Element element, String eltType, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
NodeList list = element.getElementsByTagNameNS(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, eltType);
|
||||||
|
if (list.getLength() == 1) {
|
||||||
|
Element elt = (Element) list.item(0);
|
||||||
|
helper.setAttribute(elt, RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE,
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.ID_ATTRIBUTE));
|
||||||
|
parserContext.getDelegate()
|
||||||
|
.parseCustomElement(elt, builder.getRawBeanDefinition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.redisson.client.RedisClient;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public final class RedisDefinitionParser
|
||||||
|
extends AbstractSimpleBeanDefinitionParser {
|
||||||
|
|
||||||
|
private static final String HOST_ATTRIBUTE = "host";
|
||||||
|
private static final String PORT_ATTRIBUTE = "port";
|
||||||
|
private static final String CONNECTION_TIMEOUT_ATTRIBUTE = "connectionTimeout";
|
||||||
|
private static final String COMMAND_TIMEOUT_ATTRIBUTE = "commandTimeout";
|
||||||
|
|
||||||
|
private final RedissonNamespaceParserSupport helper;
|
||||||
|
|
||||||
|
public RedisDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
this.helper = helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<RedisClient> getBeanClass(Element element) {
|
||||||
|
return RedisClient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||||
|
builder.getRawBeanDefinition().setBeanClass(RedisClient.class);
|
||||||
|
helper.addConstructorArgs(element,
|
||||||
|
HOST_ATTRIBUTE, String.class, builder);
|
||||||
|
helper.addConstructorArgs(element,
|
||||||
|
PORT_ATTRIBUTE, int.class, builder);
|
||||||
|
helper.addConstructorArgs(element,
|
||||||
|
CONNECTION_TIMEOUT_ATTRIBUTE, int.class, builder);
|
||||||
|
helper.addConstructorArgs(element,
|
||||||
|
COMMAND_TIMEOUT_ATTRIBUTE, int.class, builder);
|
||||||
|
builder.setDestroyMethodName("shutdown");
|
||||||
|
parserContext.getDelegate().parseQualifierElements(element,
|
||||||
|
builder.getRawBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldGenerateIdAsFallback() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEligibleAttribute(String attributeName) {
|
||||||
|
return helper.isEligibleAttribute(attributeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEligibleAttribute(Attr attribute, ParserContext parserContext) {
|
||||||
|
return helper.isEligibleAttribute(attribute);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.redisson.Redisson;
|
||||||
|
import org.redisson.config.Config;
|
||||||
|
import org.redisson.misc.URLBuilder;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
|
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.core.Conventions;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.util.xml.DomUtils;
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NamedNodeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public final class RedissonDefinitionParser
|
||||||
|
implements BeanDefinitionParser {
|
||||||
|
|
||||||
|
public static final String ID_ATTRIBUTE = "id";
|
||||||
|
public static final String NAME_ATTRIBUTE = "name";
|
||||||
|
private static final String REF_SUFFIX = "-ref";
|
||||||
|
private static final String REDISSON_REF = "redisson-ref";
|
||||||
|
|
||||||
|
static enum ConfigType {
|
||||||
|
singleServer,
|
||||||
|
sentinelServers,
|
||||||
|
replicatedServers,
|
||||||
|
masterSlaveServers,
|
||||||
|
clusterServers;
|
||||||
|
|
||||||
|
public static boolean contains(String type) {
|
||||||
|
try {
|
||||||
|
valueOf(type);
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum AddressType {
|
||||||
|
slaveAddress,
|
||||||
|
sentinelAddress,
|
||||||
|
nodeAddress;
|
||||||
|
|
||||||
|
public static boolean contains(String type) {
|
||||||
|
try {
|
||||||
|
valueOf(type);
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final RedissonNamespaceParserSupport helper;
|
||||||
|
|
||||||
|
RedissonDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
this.helper = helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseChildElements(Element element, String parentId, String redissonRef, BeanDefinitionBuilder redissonDef, ParserContext parserContext) {
|
||||||
|
if (element.hasChildNodes()) {
|
||||||
|
CompositeComponentDefinition compositeDef
|
||||||
|
= new CompositeComponentDefinition(parentId,
|
||||||
|
parserContext.extractSource(element));
|
||||||
|
parserContext.pushContainingComponent(compositeDef);
|
||||||
|
List<Element> childElts = DomUtils.getChildElements(element);
|
||||||
|
for (Element elt : childElts) {
|
||||||
|
if(BeanDefinitionParserDelegate
|
||||||
|
.QUALIFIER_ELEMENT.equals(elt.getLocalName())) {
|
||||||
|
continue;//parsed elsewhere
|
||||||
|
}
|
||||||
|
String localName = parserContext.getDelegate().getLocalName(elt);
|
||||||
|
localName = Conventions.attributeNameToPropertyName(localName);
|
||||||
|
if (ConfigType.contains(localName)) {
|
||||||
|
parseConfigTypes(elt, localName, redissonDef, parserContext);
|
||||||
|
} else if (AddressType.contains(localName)) {
|
||||||
|
parseAddressTypes(elt, localName, redissonDef, parserContext);
|
||||||
|
} else if (helper.isRedissonNS(elt)) {
|
||||||
|
elt.setAttribute(REDISSON_REF, redissonRef);
|
||||||
|
parserContext.getDelegate().parseCustomElement(elt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parserContext.popContainingComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseConfigTypes(Element element, String configType, BeanDefinitionBuilder redissonDef, ParserContext parserContext) {
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= helper.createBeanDefinitionBuilder(element,
|
||||||
|
parserContext, null);
|
||||||
|
//Use factory method on the Config bean
|
||||||
|
AbstractBeanDefinition bd = builder.getRawBeanDefinition();
|
||||||
|
bd.setFactoryMethodName("use" + StringUtils.capitalize(configType));
|
||||||
|
bd.setFactoryBeanName(parserContext.getContainingComponent().getName());
|
||||||
|
String id = parserContext.getReaderContext().generateBeanName(bd);
|
||||||
|
helper.registerBeanDefinition(builder, id,
|
||||||
|
helper.parseAliase(element), parserContext);
|
||||||
|
parseAttributes(element, parserContext, builder);
|
||||||
|
redissonDef.addDependsOn(id);
|
||||||
|
parseChildElements(element, id, null, redissonDef, parserContext);
|
||||||
|
parserContext.getDelegate().parseQualifierElements(element, bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseAddressTypes(Element element, String addressType, BeanDefinitionBuilder redissonDef, ParserContext parserContext) {
|
||||||
|
BeanComponentDefinition invoker = helper.invoker(element,
|
||||||
|
parserContext.getContainingComponent().getName(),
|
||||||
|
"add" + StringUtils.capitalize(addressType),
|
||||||
|
new String[]{element.getAttribute("value")},
|
||||||
|
parserContext);
|
||||||
|
String id = invoker.getName();
|
||||||
|
redissonDef.addDependsOn(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseAttributes(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||||
|
NamedNodeMap attributes = element.getAttributes();
|
||||||
|
for (int x = 0; x < attributes.getLength(); x++) {
|
||||||
|
Attr attribute = (Attr) attributes.item(x);
|
||||||
|
if (helper.isEligibleAttribute(attribute)) {
|
||||||
|
String propertyName
|
||||||
|
= attribute.getLocalName().endsWith(REF_SUFFIX)
|
||||||
|
? attribute.getLocalName()
|
||||||
|
.substring(0, attribute.getLocalName()
|
||||||
|
.length() - REF_SUFFIX.length())
|
||||||
|
: attribute.getLocalName();
|
||||||
|
propertyName = Conventions
|
||||||
|
.attributeNameToPropertyName(propertyName);
|
||||||
|
Assert.state(StringUtils.hasText(propertyName),
|
||||||
|
"Illegal property name returned from"
|
||||||
|
+ " 'extractPropertyName(String)': cannot be"
|
||||||
|
+ " null or empty.");
|
||||||
|
if (attribute.getLocalName().endsWith(REF_SUFFIX)) {
|
||||||
|
builder.addPropertyReference(propertyName,
|
||||||
|
attribute.getValue());
|
||||||
|
} else {
|
||||||
|
Object value = attribute.getValue();
|
||||||
|
String localName = helper.getName(element);
|
||||||
|
if ("masterAddress".equals(propertyName)
|
||||||
|
&& ConfigType.masterSlaveServers.name()
|
||||||
|
.equals(localName)) {
|
||||||
|
try {
|
||||||
|
value = URLBuilder.create((String) value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
//value may be a placeholder
|
||||||
|
value = "redis://" + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.addPropertyValue(propertyName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
|
//Sort out the Config Class
|
||||||
|
BeanDefinitionBuilder configBuilder
|
||||||
|
= helper.createBeanDefinitionBuilder(element, parserContext,
|
||||||
|
Config.class);
|
||||||
|
String configId = helper.getId(null, configBuilder, parserContext);
|
||||||
|
parseAttributes(element, parserContext, configBuilder);
|
||||||
|
helper.registerBeanDefinition(configBuilder, configId,
|
||||||
|
null, parserContext);
|
||||||
|
|
||||||
|
//Do the main Redisson bean
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= helper.createBeanDefinitionBuilder(element, parserContext,
|
||||||
|
Redisson.class);
|
||||||
|
builder.setFactoryMethod("create");
|
||||||
|
builder.setDestroyMethodName("shutdown");
|
||||||
|
builder.addConstructorArgReference(configId);
|
||||||
|
parserContext.getDelegate().parseQualifierElements(element,
|
||||||
|
builder.getRawBeanDefinition());
|
||||||
|
String id = helper.getId(element, builder, parserContext);
|
||||||
|
parseAttributes(element, parserContext, configBuilder);
|
||||||
|
//Sort out all the nested elements
|
||||||
|
parseChildElements(element, configId, id, builder, parserContext);
|
||||||
|
|
||||||
|
helper.registerBeanDefinition(builder, id,
|
||||||
|
helper.parseAliase(element), parserContext);
|
||||||
|
return builder.getBeanDefinition();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.redisson.api.RDestroyable;
|
||||||
|
import org.redisson.client.codec.Codec;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.core.Conventions;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonGenericObjectDefinitionParser
|
||||||
|
extends AbstractRedissonNamespaceDefinitionParser {
|
||||||
|
|
||||||
|
private final static String KEY_ATTRIBUTE = "key";
|
||||||
|
private final static String TOPIC_ATTRIBUTE = "topic";
|
||||||
|
private final static String PATTERN_ATTRIBUTE = "pattern";
|
||||||
|
private final static String SERVICE_ATTRIBUTE = "service";
|
||||||
|
private final static String CODEC_REF_ATTRIBUTE = "codec-ref";
|
||||||
|
private final static String FAIL_LOCK = "fairLock";
|
||||||
|
|
||||||
|
RedissonGenericObjectDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
super(helper, RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
RedissonGenericObjectDefinitionParser(RedissonNamespaceParserSupport helper, RedissonNamespaceDecorator decorator) {
|
||||||
|
super(helper,
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE,
|
||||||
|
decorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
|
||||||
|
bd.setFactoryBeanName(element.getAttribute(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
|
||||||
|
String typeName
|
||||||
|
= Conventions.attributeNameToPropertyName(element.getLocalName());
|
||||||
|
bd.setFactoryMethodName("get" + StringUtils.capitalize(typeName));
|
||||||
|
|
||||||
|
helper.addConstructorArgs(element, KEY_ATTRIBUTE,
|
||||||
|
String.class, builder);
|
||||||
|
helper.addConstructorArgs(element, TOPIC_ATTRIBUTE,
|
||||||
|
String.class, builder);
|
||||||
|
helper.addConstructorArgs(element, PATTERN_ATTRIBUTE,
|
||||||
|
String.class, builder);
|
||||||
|
helper.addConstructorArgs(element, SERVICE_ATTRIBUTE,
|
||||||
|
String.class, builder);
|
||||||
|
helper.addConstructorArgs(element, CODEC_REF_ATTRIBUTE,
|
||||||
|
Codec.class, builder);
|
||||||
|
if (RDestroyable.class.isAssignableFrom(getBeanClass(element))) {
|
||||||
|
((AbstractBeanDefinition) bd).setDestroyMethodName("destroy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> getBeanClass(Element element) {
|
||||||
|
String elementName
|
||||||
|
= Conventions.attributeNameToPropertyName(
|
||||||
|
element.getLocalName());
|
||||||
|
try {
|
||||||
|
return Class.forName(RedissonNamespaceParserSupport.API_CLASS_PATH_PREFIX
|
||||||
|
+ (StringUtils.capitalize(FAIL_LOCK.equals(elementName)
|
||||||
|
? "lock"
|
||||||
|
: elementName)));
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new IllegalArgumentException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.ManagedList;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import reactor.core.support.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonLiveObjectDefinitionParser
|
||||||
|
extends AbstractRedissonNamespaceDefinitionParser {
|
||||||
|
|
||||||
|
public RedissonLiveObjectDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
super(helper, RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
|
||||||
|
Class<?> apiClass;
|
||||||
|
try {
|
||||||
|
apiClass = Class.forName(helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE));
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The class [" + helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE)
|
||||||
|
+ "] specified in \"api-class\" attribute has not "
|
||||||
|
+ "found. Please check the class path.", ex);
|
||||||
|
}
|
||||||
|
Assert.state(helper.hasAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE)
|
||||||
|
|| helper.hasAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE),
|
||||||
|
"One of \""
|
||||||
|
+ RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE
|
||||||
|
+ "\" or \""
|
||||||
|
+ RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE
|
||||||
|
+ "\" attribute is required in the \""
|
||||||
|
+ RedissonNamespaceParserSupport.LIVE_OBJECT_ELEMENT
|
||||||
|
+ "\" element.");
|
||||||
|
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE)));
|
||||||
|
builder.addPropertyValue("targetMethod", "get");
|
||||||
|
ManagedList args = new ManagedList();
|
||||||
|
args.add(apiClass);
|
||||||
|
if (helper.hasAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE)) {
|
||||||
|
args.add(helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.OBJECT_ID_ATTRIBUTE));
|
||||||
|
}
|
||||||
|
if (helper.hasAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE)) {
|
||||||
|
args.add(new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.OBJECT_ID_REF_ATTRIBUTE)));
|
||||||
|
}
|
||||||
|
builder.addPropertyValue("arguments", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> getBeanClass(Element element) {
|
||||||
|
return MethodInvokingFactoryBean.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.redisson.spring.misc.BeanMethodInvoker;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonLiveObjectRegistrationDefinitionParser
|
||||||
|
extends AbstractRedissonNamespaceDefinitionParser {
|
||||||
|
|
||||||
|
public RedissonLiveObjectRegistrationDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
super(helper,
|
||||||
|
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
|
||||||
|
Class<?> apiClass;
|
||||||
|
try {
|
||||||
|
apiClass = Class.forName(helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE));
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The class [" + helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.CLASS_ATTRIBUTE)
|
||||||
|
+ "] specified in \"api-class\" attribute has not "
|
||||||
|
+ "found. Please check the class path.", ex);
|
||||||
|
}
|
||||||
|
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE)));
|
||||||
|
builder.addPropertyValue("targetMethod", "registerClass");
|
||||||
|
builder.addPropertyValue("arguments", new Object[] {apiClass});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> getBeanClass(Element element) {
|
||||||
|
return BeanMethodInvoker.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.ManagedList;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.core.Conventions;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.util.xml.DomUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonMultiLockDefinitionParser
|
||||||
|
extends AbstractRedissonNamespaceDefinitionParser {
|
||||||
|
|
||||||
|
public RedissonMultiLockDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
super(helper,
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
|
||||||
|
bd.setDependsOn(element.getAttribute(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
|
||||||
|
List<Element> childElements = DomUtils.getChildElements(element);
|
||||||
|
for (Element elt : childElements) {
|
||||||
|
String localName = elt.getLocalName();
|
||||||
|
if (BeanDefinitionParserDelegate
|
||||||
|
.QUALIFIER_ELEMENT.equals(localName)) {
|
||||||
|
continue;//parsed elsewhere
|
||||||
|
}
|
||||||
|
String id;
|
||||||
|
if (BeanDefinitionParserDelegate.REF_ELEMENT.equals(localName)){
|
||||||
|
id = elt.getAttribute(
|
||||||
|
BeanDefinitionParserDelegate.BEAN_REF_ATTRIBUTE);
|
||||||
|
} else {
|
||||||
|
if (!elt.hasAttribute(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE)) {
|
||||||
|
helper.setAttribute(elt,
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE,
|
||||||
|
element.getAttribute(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
|
||||||
|
}
|
||||||
|
helper.populateIdAttribute(elt, builder, parserContext);
|
||||||
|
parserContext.getDelegate().parseCustomElement(elt, bd);
|
||||||
|
id = elt.getAttribute(
|
||||||
|
RedissonNamespaceParserSupport.ID_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
ConstructorArgumentValues args
|
||||||
|
= builder.getRawBeanDefinition()
|
||||||
|
.getConstructorArgumentValues();
|
||||||
|
if (args.getArgumentCount() > 0) {
|
||||||
|
ConstructorArgumentValues.ValueHolder value
|
||||||
|
= args.getIndexedArgumentValues().get(0);
|
||||||
|
ManagedList list;
|
||||||
|
if (value.getValue() instanceof ManagedList) {
|
||||||
|
list = (ManagedList) value.getValue();
|
||||||
|
} else {
|
||||||
|
list = new ManagedList();
|
||||||
|
list.add(value.getValue());
|
||||||
|
value.setValue(list);
|
||||||
|
value.setType(ManagedList.class.getName());
|
||||||
|
}
|
||||||
|
list.add(new RuntimeBeanReference(id));
|
||||||
|
} else {
|
||||||
|
builder.addConstructorArgReference(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getBeanClassName(Element element) {
|
||||||
|
String elementName
|
||||||
|
= Conventions.attributeNameToPropertyName(
|
||||||
|
element.getLocalName());
|
||||||
|
return RedissonNamespaceParserSupport.IMPL_CLASS_PATH_PREFIX
|
||||||
|
+ StringUtils.capitalize(elementName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public interface RedissonNamespaceDecorator {
|
||||||
|
|
||||||
|
void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper);
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonNamespaceDefaultDecorator implements RedissonNamespaceDecorator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
//default is no decoration;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonNamespaceHandlerSupport extends NamespaceHandlerSupport {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
RedissonNamespaceParserSupport helper
|
||||||
|
= new RedissonNamespaceParserSupport();
|
||||||
|
|
||||||
|
RedissonGenericObjectDefinitionParser defaultParser
|
||||||
|
= new RedissonGenericObjectDefinitionParser(helper);
|
||||||
|
|
||||||
|
RedissonReadAndWriteLockDefinitionParser readAndWriteLockParser
|
||||||
|
= new RedissonReadAndWriteLockDefinitionParser(helper);
|
||||||
|
|
||||||
|
RedissonMultiLockDefinitionParser nestedParser
|
||||||
|
= new RedissonMultiLockDefinitionParser(helper);
|
||||||
|
|
||||||
|
RedissonNestedElementAwareDecorator readWriteLockDecorator
|
||||||
|
= new RedissonNestedElementAwareDecorator(
|
||||||
|
new String[]{
|
||||||
|
RedissonNamespaceParserSupport.READ_LOCK_ELEMENT,
|
||||||
|
RedissonNamespaceParserSupport.WRITE_LOCK_ELEMENT
|
||||||
|
},
|
||||||
|
RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE);
|
||||||
|
|
||||||
|
RedissonGenericObjectDefinitionParser readWriteLockParser
|
||||||
|
= new RedissonGenericObjectDefinitionParser(helper,
|
||||||
|
readWriteLockDecorator);
|
||||||
|
|
||||||
|
RedissonNestedElementAwareDecorator remoteServiceDecorator
|
||||||
|
= new RedissonNestedElementAwareDecorator(
|
||||||
|
new String[]{
|
||||||
|
RedissonNamespaceParserSupport.RPC_SERVER_ELEMENT,
|
||||||
|
RedissonNamespaceParserSupport.RPC_CLIENT_ELEMENT
|
||||||
|
},
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE);
|
||||||
|
|
||||||
|
RedissonGenericObjectDefinitionParser remoteServiceParser
|
||||||
|
= new RedissonGenericObjectDefinitionParser(helper,
|
||||||
|
remoteServiceDecorator);
|
||||||
|
|
||||||
|
RedissonNestedElementAwareDecorator liveObjectServiceDecorator
|
||||||
|
= new RedissonNestedElementAwareDecorator(
|
||||||
|
new String[]{
|
||||||
|
RedissonNamespaceParserSupport.LIVE_OBJECT_ELEMENT,
|
||||||
|
RedissonNamespaceParserSupport.LIVE_OBJECT_REGISTRATION_ELEMENT
|
||||||
|
},
|
||||||
|
RedissonNamespaceParserSupport.LIVE_OBJECT_SERVICE_REF_ATTRIBUTE);
|
||||||
|
|
||||||
|
RedissonGenericObjectDefinitionParser liveObjectServiceParser
|
||||||
|
= new RedissonGenericObjectDefinitionParser(helper,
|
||||||
|
liveObjectServiceDecorator);
|
||||||
|
|
||||||
|
//root beans
|
||||||
|
registerBeanDefinitionParser("client",
|
||||||
|
new RedissonDefinitionParser(helper));
|
||||||
|
registerBeanDefinitionParser("redis", new RedisDefinitionParser(helper));
|
||||||
|
//object parsers
|
||||||
|
registerBeanDefinitionParser("binary-stream", defaultParser);
|
||||||
|
registerBeanDefinitionParser("geo", defaultParser);
|
||||||
|
registerBeanDefinitionParser("set-cache", defaultParser);
|
||||||
|
registerBeanDefinitionParser("map-cache", defaultParser);
|
||||||
|
registerBeanDefinitionParser("bucket", defaultParser);
|
||||||
|
registerBeanDefinitionParser("buckets", defaultParser);
|
||||||
|
registerBeanDefinitionParser("hyper-log-log", defaultParser);
|
||||||
|
registerBeanDefinitionParser("list", defaultParser);
|
||||||
|
registerBeanDefinitionParser("list-multimap", defaultParser);
|
||||||
|
registerBeanDefinitionParser("list-multimap-cache", defaultParser);
|
||||||
|
registerBeanDefinitionParser("local-cached-map",
|
||||||
|
new RedissonGenericObjectDefinitionParser(helper,
|
||||||
|
new LocalCachedMapOptionsDecorator()));
|
||||||
|
registerBeanDefinitionParser("map", defaultParser);
|
||||||
|
registerBeanDefinitionParser("set-multimap", defaultParser);
|
||||||
|
registerBeanDefinitionParser("set-multimap-cache", defaultParser);
|
||||||
|
registerBeanDefinitionParser("semaphore", defaultParser);
|
||||||
|
registerBeanDefinitionParser("permit-expirable-semaphore", defaultParser);
|
||||||
|
registerBeanDefinitionParser("lock", defaultParser);
|
||||||
|
registerBeanDefinitionParser("fair-lock", defaultParser);
|
||||||
|
registerBeanDefinitionParser("read-write-lock",readWriteLockParser);
|
||||||
|
registerBeanDefinitionParser("read-lock", readAndWriteLockParser);
|
||||||
|
registerBeanDefinitionParser("write-lock", readAndWriteLockParser);
|
||||||
|
registerBeanDefinitionParser("multi-lock", nestedParser);
|
||||||
|
registerBeanDefinitionParser("red-lock", nestedParser);
|
||||||
|
registerBeanDefinitionParser("set", defaultParser);
|
||||||
|
registerBeanDefinitionParser("sorted-set", defaultParser);
|
||||||
|
registerBeanDefinitionParser("scored-sorted-set", defaultParser);
|
||||||
|
registerBeanDefinitionParser("lex-sorted-set", defaultParser);
|
||||||
|
registerBeanDefinitionParser("topic", defaultParser);
|
||||||
|
registerBeanDefinitionParser("pattern-topic", defaultParser);
|
||||||
|
registerBeanDefinitionParser("blocking-fair-queue", defaultParser);
|
||||||
|
registerBeanDefinitionParser("queue", defaultParser);
|
||||||
|
registerBeanDefinitionParser("delayed-queue",
|
||||||
|
new RedissonGenericObjectDefinitionParser(helper,
|
||||||
|
new DelayedQueueDecorator()));
|
||||||
|
registerBeanDefinitionParser("priority-queue", defaultParser);
|
||||||
|
registerBeanDefinitionParser("priority-deque", defaultParser);
|
||||||
|
registerBeanDefinitionParser("blocking-queue", defaultParser);
|
||||||
|
registerBeanDefinitionParser("bounded-blocking-queue", defaultParser);
|
||||||
|
registerBeanDefinitionParser("deque", defaultParser);
|
||||||
|
registerBeanDefinitionParser("blocking-deque", defaultParser);
|
||||||
|
registerBeanDefinitionParser("atomic-long", defaultParser);
|
||||||
|
registerBeanDefinitionParser("atomic-double", defaultParser);
|
||||||
|
registerBeanDefinitionParser("count-down-latch", defaultParser);
|
||||||
|
registerBeanDefinitionParser("bit-set", defaultParser);
|
||||||
|
registerBeanDefinitionParser("bloom-filter", defaultParser);
|
||||||
|
registerBeanDefinitionParser("script", defaultParser);
|
||||||
|
registerBeanDefinitionParser("executor-service", defaultParser);//nested unfinished
|
||||||
|
registerBeanDefinitionParser("remote-service", remoteServiceParser);
|
||||||
|
registerBeanDefinitionParser("rpc-server",
|
||||||
|
new RedissonRPCServerDefinitionParser(helper));
|
||||||
|
registerBeanDefinitionParser("rpc-client",
|
||||||
|
new RedissonRPCClientDefinitionParser(helper,
|
||||||
|
new RemoteInvocationOptionDecorator()));
|
||||||
|
registerBeanDefinitionParser("keys", defaultParser);
|
||||||
|
registerBeanDefinitionParser("live-object-service", liveObjectServiceParser);
|
||||||
|
registerBeanDefinitionParser("live-object",
|
||||||
|
new RedissonLiveObjectDefinitionParser(helper));
|
||||||
|
registerBeanDefinitionParser("live-object-registration",
|
||||||
|
new RedissonLiveObjectRegistrationDefinitionParser(helper));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,300 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.redisson.spring.misc.BeanMethodInvoker;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||||
|
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||||
|
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||||
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.core.Conventions;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonNamespaceParserSupport {
|
||||||
|
|
||||||
|
public final static String REDISSON_NAMESPACE
|
||||||
|
= "http://redisson.org/schema/redisson";
|
||||||
|
|
||||||
|
static final String API_CLASS_PATH_PREFIX = "org.redisson.api.R";
|
||||||
|
static final String IMPL_CLASS_PATH_PREFIX = "org.redisson.Redisson";
|
||||||
|
|
||||||
|
static final String ID_ATTRIBUTE = "id";
|
||||||
|
static final String NAME_ATTRIBUTE = "name";
|
||||||
|
static final String REDISSON_REF_ATTRIBUTE = "redisson-ref";
|
||||||
|
static final String READ_WRITE_LOCK_REF_ATTRIBUTE = "read-write-lock-ref";
|
||||||
|
static final String EXECUTOR_REF_ATTRIBUTE = "executor-ref";
|
||||||
|
static final String REMOTE_SERVICE_REF_ATTRIBUTE = "remote-service-ref";
|
||||||
|
static final String LIVE_OBJECT_SERVICE_REF_ATTRIBUTE
|
||||||
|
= "live-object-service-ref";
|
||||||
|
static final String OBJECT_ID_REF_ATTRIBUTE = "object-id-ref";
|
||||||
|
|
||||||
|
static final String MAX_IDLE_ATTRIBUTE = "max-idle";
|
||||||
|
static final String TIME_TO_LIVE_ATTRIBUTE = "time-to-live";
|
||||||
|
static final String MAX_IDLE_UNIT_ATTRIBUTE = "max-idle-unit";
|
||||||
|
static final String TIME_TO_LIVE_UNIT_ATTRIBUTE = "time-to-live-unit";
|
||||||
|
static final String CONCURRENT_WORKERS_ATTRIBUTE = "concurrent-workers";
|
||||||
|
static final String WITHIN_ATTRIBUTE = "within";
|
||||||
|
static final String TIME_UNIT_ATTRIBUTE = "time-unit";
|
||||||
|
static final String API_CLASS_ATTRIBUTE = "api-class";
|
||||||
|
static final String CLASS_ATTRIBUTE = "class";
|
||||||
|
static final String OBJECT_ID_ATTRIBUTE = "object-id";
|
||||||
|
|
||||||
|
static final String READ_LOCK_ELEMENT = "read-lock";
|
||||||
|
static final String WRITE_LOCK_ELEMENT = "write-lock";
|
||||||
|
static final String RPC_SERVER_ELEMENT = "rpc-server";
|
||||||
|
static final String RPC_CLIENT_ELEMENT = "rpc-client";
|
||||||
|
static final String REMOTE_INVOCATION_OPTIONS_ELEMENT
|
||||||
|
= "remote-invocation-options";
|
||||||
|
static final String REMOTE_NO_ACK_ELEMENT = "remote-no-ack";
|
||||||
|
static final String REMOTE_ACK_ELEMENT = "remote-ack";
|
||||||
|
static final String REMOTE_NO_RESULT_ELEMENT = "remote-no-result";
|
||||||
|
static final String REMOTE_RESULT_ELEMENT = "remote-result";
|
||||||
|
static final String LOCAL_CACHED_MAP_OPTIONS_ELEMENT
|
||||||
|
= "local-cached-map-options";
|
||||||
|
static final String LIVE_OBJECT_ELEMENT
|
||||||
|
= "live-object";
|
||||||
|
static final String LIVE_OBJECT_REGISTRATION_ELEMENT
|
||||||
|
= "live-object-registration";
|
||||||
|
|
||||||
|
public String[] parseAliase(Element element) {
|
||||||
|
if (element == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String[] aliases = null;
|
||||||
|
String name = element.getAttribute(NAME_ATTRIBUTE);
|
||||||
|
if (StringUtils.hasLength(name)) {
|
||||||
|
aliases = StringUtils.trimArrayElements(
|
||||||
|
StringUtils.commaDelimitedListToStringArray(name));
|
||||||
|
}
|
||||||
|
return aliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanDefinitionBuilder createBeanDefinitionBuilder(Element element, ParserContext parserContext, Class<?> cls) {
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= BeanDefinitionBuilder.genericBeanDefinition();
|
||||||
|
builder.getRawBeanDefinition().setBeanClass(cls);
|
||||||
|
builder.getRawBeanDefinition()
|
||||||
|
.setSource(parserContext.extractSource(element));
|
||||||
|
if (parserContext.isNested()) {
|
||||||
|
builder.setScope(parserContext.getContainingBeanDefinition()
|
||||||
|
.getScope());
|
||||||
|
}
|
||||||
|
if (parserContext.isDefaultLazyInit()) {
|
||||||
|
builder.setLazyInit(true);
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanComponentDefinition registerBeanDefinition(BeanDefinitionBuilder builder, String id, String[] aliases, ParserContext parserContext) {
|
||||||
|
BeanDefinitionHolder holder
|
||||||
|
= new BeanDefinitionHolder(builder.getBeanDefinition(), id,
|
||||||
|
aliases);
|
||||||
|
BeanDefinitionReaderUtils
|
||||||
|
.registerBeanDefinition(holder, parserContext.getRegistry());
|
||||||
|
BeanComponentDefinition componentDefinition
|
||||||
|
= new BeanComponentDefinition(holder);
|
||||||
|
parserContext.registerComponent(componentDefinition);
|
||||||
|
return componentDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanComponentDefinition registerBeanDefinition(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
|
||||||
|
BeanDefinitionHolder holder
|
||||||
|
= new BeanDefinitionHolder(builder.getBeanDefinition(),
|
||||||
|
getId(element, builder, parserContext),
|
||||||
|
parseAliase(element));
|
||||||
|
BeanDefinitionReaderUtils
|
||||||
|
.registerBeanDefinition(holder, parserContext.getRegistry());
|
||||||
|
BeanComponentDefinition componentDefinition
|
||||||
|
= new BeanComponentDefinition(holder);
|
||||||
|
parserContext.registerComponent(componentDefinition);
|
||||||
|
return componentDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructorArgs(Element element, String attribute, Class type, BeanDefinition bd) {
|
||||||
|
if (element.hasAttribute(attribute)) {
|
||||||
|
addConstructorArgs(element.getAttribute(attribute), type, bd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructorArgs(Object value, Class type, BeanDefinition bd) {
|
||||||
|
ConstructorArgumentValues.ValueHolder vHolder
|
||||||
|
= new ConstructorArgumentValues.ValueHolder(value, type.getName());
|
||||||
|
ConstructorArgumentValues args
|
||||||
|
= bd.getConstructorArgumentValues();
|
||||||
|
args.addIndexedArgumentValue(args.getArgumentCount(), vHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructorArgs(Element element, String attribute, Class type, BeanDefinitionBuilder builder) {
|
||||||
|
addConstructorArgs(element, attribute, type, builder.getRawBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructorArgs(Object value, Class type, BeanDefinitionBuilder builder) {
|
||||||
|
addConstructorArgs(value, type, builder.getRawBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(Node node) {
|
||||||
|
return Conventions.attributeNameToPropertyName(node.getLocalName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) {
|
||||||
|
String id = element != null
|
||||||
|
? element.getAttribute(ID_ATTRIBUTE)
|
||||||
|
: null;
|
||||||
|
if (!StringUtils.hasText(id)) {
|
||||||
|
id = generateId(builder, parserContext);
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateId(BeanDefinitionBuilder builder, ParserContext parserContext) {
|
||||||
|
return parserContext.getReaderContext()
|
||||||
|
.generateBeanName(builder.getRawBeanDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void populateIdAttribute(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) {
|
||||||
|
if (element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!StringUtils.hasText(element.getAttribute(ID_ATTRIBUTE))) {
|
||||||
|
element.setAttribute(ID_ATTRIBUTE,
|
||||||
|
generateId(builder, parserContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanComponentDefinition factoryInvoker(Element element, String bean, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= preInvoke(element, bean, method, args, parserContext, true);
|
||||||
|
builder.addPropertyReference("targetObject", bean);
|
||||||
|
return doInvoke(element, builder, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanComponentDefinition factoryInvoker(Element element, Object obj, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= preInvoke(element, obj, method, args, parserContext, true);
|
||||||
|
builder.addPropertyValue("targetObject", obj);
|
||||||
|
return doInvoke(element, builder, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BeanComponentDefinition factoryInvoker(String bean, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
return factoryInvoker(null, bean, method, args, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanComponentDefinition factoryInvoker(Object obj, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
return factoryInvoker(null, obj, method, args, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BeanComponentDefinition invoker(Element element, String bean, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= preInvoke(element, bean, method, args, parserContext, false);
|
||||||
|
builder.addPropertyReference("targetObject", bean);
|
||||||
|
return doInvoke(element, builder, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanComponentDefinition invoker(Element element, Object obj, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= preInvoke(element, obj, method, args, parserContext, false);
|
||||||
|
builder.addPropertyValue("targetObject", obj);
|
||||||
|
return doInvoke(element, builder, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BeanComponentDefinition invoker(String bean, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
return invoker(null, bean, method, args, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeanComponentDefinition invoker(Object obj, String method, Object[] args, ParserContext parserContext) {
|
||||||
|
return invoker(null, obj, method, args, parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BeanDefinitionBuilder preInvoke(Element element, Object obj, String method, Object[] args, ParserContext parserContext, boolean factory) {
|
||||||
|
BeanDefinitionBuilder builder
|
||||||
|
= createBeanDefinitionBuilder(element, parserContext,
|
||||||
|
factory
|
||||||
|
? MethodInvokingFactoryBean.class
|
||||||
|
: BeanMethodInvoker.class);
|
||||||
|
if (obj instanceof Class) {
|
||||||
|
builder.addPropertyValue("staticMethod",
|
||||||
|
((Class) obj).getName() + "." + method);
|
||||||
|
} else {
|
||||||
|
builder.addPropertyValue("targetMethod", method);
|
||||||
|
}
|
||||||
|
builder.addPropertyValue("arguments", args);
|
||||||
|
if (element != null) {
|
||||||
|
parserContext.getDelegate().parseQualifierElements(element,
|
||||||
|
builder.getRawBeanDefinition());
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BeanComponentDefinition doInvoke(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) {
|
||||||
|
String id = getId(element, builder, parserContext);
|
||||||
|
return registerBeanDefinition(builder, id,
|
||||||
|
parseAliase(element), parserContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEligibleAttribute(String attributeName) {
|
||||||
|
return !attributeName.equals("xmlns")
|
||||||
|
&& !attributeName.startsWith("xmlns:")
|
||||||
|
&& !ID_ATTRIBUTE.equals(attributeName)
|
||||||
|
&& !NAME_ATTRIBUTE.equals(attributeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEligibleAttribute(Attr attribute) {
|
||||||
|
return isEligibleAttribute(attribute.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRedissonNS(Node node) {
|
||||||
|
return node != null
|
||||||
|
&& REDISSON_NAMESPACE.equals(node.getNamespaceURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttribute(Element element, String attribute) {
|
||||||
|
return element.getAttribute(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttribute(Element element, String attribute, String value) {
|
||||||
|
element.setAttribute(attribute, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAttribute(Element element, String attribute) {
|
||||||
|
return element.hasAttribute(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasElement(Element element, String tagName) {
|
||||||
|
return element.getElementsByTagNameNS(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, tagName)
|
||||||
|
.getLength() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element getSingleElement(Element element, String tagName) {
|
||||||
|
return (Element) element.getElementsByTagNameNS(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, tagName)
|
||||||
|
.item(0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonNestedElementAwareDecorator implements RedissonNamespaceDecorator {
|
||||||
|
|
||||||
|
private final String[] nestedElements;
|
||||||
|
private final String referenceAttribute;
|
||||||
|
|
||||||
|
public RedissonNestedElementAwareDecorator(String[] nestedElements, String referenceAttribute) {
|
||||||
|
this.nestedElements = nestedElements;
|
||||||
|
this.referenceAttribute = referenceAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
for (String nestedElement : nestedElements) {
|
||||||
|
parseNested(element, nestedElement, parserContext, builder, helper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseNested(Element element, String eltType, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
NodeList list = element.getElementsByTagNameNS(
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_NAMESPACE, eltType);
|
||||||
|
if (list.getLength() == 1) {
|
||||||
|
Element elt = (Element) list.item(0);
|
||||||
|
if (StringUtils.hasText(referenceAttribute)) {
|
||||||
|
helper.setAttribute(elt, referenceAttribute,
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.ID_ATTRIBUTE));
|
||||||
|
helper.setAttribute(elt, RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE,
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.REDISSON_REF_ATTRIBUTE));
|
||||||
|
}
|
||||||
|
parserContext.getDelegate()
|
||||||
|
.parseCustomElement(elt, builder.getRawBeanDefinition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonRPCClientDefinitionParser
|
||||||
|
extends AbstractRedissonNamespaceDefinitionParser {
|
||||||
|
|
||||||
|
public RedissonRPCClientDefinitionParser(RedissonNamespaceParserSupport helper, RedissonNamespaceDecorator decorator) {
|
||||||
|
super(helper,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE,
|
||||||
|
decorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
|
||||||
|
Class<?> apiClass;
|
||||||
|
try {
|
||||||
|
apiClass = Class.forName(helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE));
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The class [" + helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE)
|
||||||
|
+ "] specified in \""
|
||||||
|
+ RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE
|
||||||
|
+ "\" attribute has not "
|
||||||
|
+ "found. Please check the class path.", ex);
|
||||||
|
}
|
||||||
|
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE)));
|
||||||
|
builder.addPropertyValue("targetMethod", "get");
|
||||||
|
builder.addPropertyValue("arguments", new Object[] {apiClass});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> getBeanClass(Element element) {
|
||||||
|
return MethodInvokingFactoryBean.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.redisson.spring.misc.BeanMethodInvoker;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.ManagedList;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import reactor.core.support.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonRPCServerDefinitionParser
|
||||||
|
extends AbstractRedissonNamespaceDefinitionParser {
|
||||||
|
|
||||||
|
public RedissonRPCServerDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
super(helper, RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
|
||||||
|
Class<?> apiClass;
|
||||||
|
try {
|
||||||
|
apiClass = Class.forName(helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE));
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The class [" + helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE)
|
||||||
|
+ "] specified in \""
|
||||||
|
+ RedissonNamespaceParserSupport.API_CLASS_ATTRIBUTE
|
||||||
|
+ "\" attribute has not "
|
||||||
|
+ "found. Please check the class path.", ex);
|
||||||
|
}
|
||||||
|
builder.addPropertyValue("targetObject", new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_SERVICE_REF_ATTRIBUTE)));
|
||||||
|
builder.addPropertyValue("targetMethod", "register");
|
||||||
|
ManagedList args = new ManagedList();
|
||||||
|
args.add(apiClass);
|
||||||
|
args.add(new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element,
|
||||||
|
BeanDefinitionParserDelegate.BEAN_REF_ATTRIBUTE)));
|
||||||
|
String workers = null;
|
||||||
|
if (helper.hasAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE)) {
|
||||||
|
workers = helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(workers)) {
|
||||||
|
args.add(Integer.parseInt(workers));
|
||||||
|
}
|
||||||
|
if (helper.hasAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.EXECUTOR_REF_ATTRIBUTE)) {
|
||||||
|
Assert.state(helper.hasAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE),
|
||||||
|
"The \""
|
||||||
|
+ RedissonNamespaceParserSupport.CONCURRENT_WORKERS_ATTRIBUTE
|
||||||
|
+ "\" attribute in \""
|
||||||
|
+ RedissonNamespaceParserSupport.RPC_SERVER_ELEMENT
|
||||||
|
+ "\" element is required when \""
|
||||||
|
+ RedissonNamespaceParserSupport.EXECUTOR_REF_ATTRIBUTE
|
||||||
|
+ "\" attribute is specified.");
|
||||||
|
args.add(new RuntimeBeanReference(
|
||||||
|
helper.getAttribute(element,
|
||||||
|
RedissonNamespaceParserSupport.EXECUTOR_REF_ATTRIBUTE)));
|
||||||
|
}
|
||||||
|
builder.addPropertyValue("arguments", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> getBeanClass(Element element) {
|
||||||
|
return BeanMethodInvoker.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.core.Conventions;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RedissonReadAndWriteLockDefinitionParser
|
||||||
|
extends AbstractRedissonNamespaceDefinitionParser {
|
||||||
|
|
||||||
|
public RedissonReadAndWriteLockDefinitionParser(RedissonNamespaceParserSupport helper) {
|
||||||
|
super(helper,
|
||||||
|
RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseNested(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinition bd) {
|
||||||
|
bd.setFactoryBeanName(element.getAttribute(
|
||||||
|
RedissonNamespaceParserSupport.READ_WRITE_LOCK_REF_ATTRIBUTE));
|
||||||
|
String typeName
|
||||||
|
= Conventions.attributeNameToPropertyName(element.getLocalName());
|
||||||
|
bd.setFactoryMethodName(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> getBeanClass(Element element) {
|
||||||
|
try {
|
||||||
|
return Class.forName(RedissonNamespaceParserSupport.API_CLASS_PATH_PREFIX
|
||||||
|
+ "Lock");
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new IllegalArgumentException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Nikita Koksharov
|
||||||
|
*
|
||||||
|
* 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.redisson.spring.support;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.redisson.api.RemoteInvocationOptions;
|
||||||
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
|
import org.springframework.beans.PropertyValue;
|
||||||
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.ManagedList;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import reactor.core.support.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class RemoteInvocationOptionDecorator implements RedissonNamespaceDecorator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decorate(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, RedissonNamespaceParserSupport helper) {
|
||||||
|
if (helper.hasElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_INVOCATION_OPTIONS_ELEMENT)) {
|
||||||
|
Element options = helper.getSingleElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_INVOCATION_OPTIONS_ELEMENT);
|
||||||
|
String optionBeanId = invokeOptions(options, parserContext, helper);
|
||||||
|
if (helper.hasElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_NO_ACK_ELEMENT)) {
|
||||||
|
helper.invoker(optionBeanId, "noAck", null, parserContext);
|
||||||
|
}
|
||||||
|
if (helper.hasElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_ACK_ELEMENT)) {
|
||||||
|
Element remoteAck = helper.getSingleElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_ACK_ELEMENT);
|
||||||
|
Assert.state(helper.hasAttribute(remoteAck,
|
||||||
|
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE),
|
||||||
|
"Missing \""
|
||||||
|
+ RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE
|
||||||
|
+ "\" attribute in \""
|
||||||
|
+ RedissonNamespaceParserSupport.REMOTE_ACK_ELEMENT
|
||||||
|
+ "\" element.");
|
||||||
|
ArrayList args = new ArrayList(2);
|
||||||
|
args.add(helper.getAttribute(remoteAck,
|
||||||
|
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE));
|
||||||
|
if (helper.hasAttribute(remoteAck,
|
||||||
|
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE)) {
|
||||||
|
args.add(helper.getAttribute(remoteAck,
|
||||||
|
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE));
|
||||||
|
}
|
||||||
|
helper.invoker(optionBeanId, "expectAckWithin", args.toArray(),
|
||||||
|
parserContext);
|
||||||
|
}
|
||||||
|
if (helper.hasElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_NO_RESULT_ELEMENT)) {
|
||||||
|
helper.invoker(optionBeanId, "noResult", null, parserContext);
|
||||||
|
}
|
||||||
|
if (helper.hasElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_RESULT_ELEMENT)) {
|
||||||
|
Element remoteResult = helper.getSingleElement(element,
|
||||||
|
RedissonNamespaceParserSupport.REMOTE_RESULT_ELEMENT);
|
||||||
|
Assert.state(helper.hasAttribute(remoteResult,
|
||||||
|
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE),
|
||||||
|
"Missing \""
|
||||||
|
+ RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE
|
||||||
|
+ "\" attribute in \""
|
||||||
|
+ RedissonNamespaceParserSupport.REMOTE_RESULT_ELEMENT
|
||||||
|
+ "\" element.");
|
||||||
|
ArrayList args = new ArrayList(2);
|
||||||
|
args.add(helper.getAttribute(remoteResult,
|
||||||
|
RedissonNamespaceParserSupport.WITHIN_ATTRIBUTE));
|
||||||
|
if (helper.hasAttribute(remoteResult,
|
||||||
|
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE)) {
|
||||||
|
args.add(helper.getAttribute(remoteResult,
|
||||||
|
RedissonNamespaceParserSupport.TIME_UNIT_ATTRIBUTE));
|
||||||
|
}
|
||||||
|
helper.invoker(optionBeanId, "expectResultWithin", args.toArray(),
|
||||||
|
parserContext);
|
||||||
|
}
|
||||||
|
MutablePropertyValues properties = builder.getRawBeanDefinition()
|
||||||
|
.getPropertyValues();
|
||||||
|
PropertyValue propertyValue
|
||||||
|
= properties.getPropertyValue("arguments");
|
||||||
|
ManagedList<Object> args = new ManagedList();
|
||||||
|
args.addAll(Arrays.asList(
|
||||||
|
(Object[]) propertyValue.getValue()));
|
||||||
|
args.add(new RuntimeBeanReference(optionBeanId));
|
||||||
|
properties.removePropertyValue("arguments");
|
||||||
|
properties.addPropertyValue("arguments", args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String invokeOptions(Element element, ParserContext parserContext, RedissonNamespaceParserSupport helper) {
|
||||||
|
BeanComponentDefinition defaultOption
|
||||||
|
= helper.factoryInvoker(element, RemoteInvocationOptions.class,
|
||||||
|
"defaults", null, parserContext);
|
||||||
|
return defaultOption.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
http\://redisson.org/schema/redisson=org.redisson.spring.support.RedissonNamespaceHandlerSupport
|
@ -0,0 +1,2 @@
|
|||||||
|
http\://redisson.org/schema/redisson.xsd=org/redisson/spring/support/redisson-1.0.xsd
|
||||||
|
http\://redisson.org/schema/redisson-1.0.xsd=org/redisson/spring/support/redisson-1.0.xsd
|
@ -0,0 +1,4 @@
|
|||||||
|
# Tooling related information for the redisson namespace
|
||||||
|
http\://redisson.org/schema/redisson@name=redisson Namespace
|
||||||
|
http\://redisson.org/schema/redisson@prefix=redisson
|
||||||
|
http\://redisson.org/schema/redisson@icon=org/redisson/spring/support/redisson.gif
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,99 @@
|
|||||||
|
package org.redisson;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class ClusterRunner {
|
||||||
|
|
||||||
|
private final LinkedHashMap<RedisRunner, String> nodes = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
public ClusterRunner addNode(RedisRunner runner) {
|
||||||
|
nodes.put(runner, getRandomId());
|
||||||
|
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.CLUSTER_ENABLED)) {
|
||||||
|
runner.clusterEnabled(true);
|
||||||
|
}
|
||||||
|
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.CLUSTER_NODE_TIMEOUT)) {
|
||||||
|
runner.clusterNodeTimeout(5000);
|
||||||
|
}
|
||||||
|
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.PORT)) {
|
||||||
|
runner.randomPort(1);
|
||||||
|
runner.port(RedisRunner.findFreePort());
|
||||||
|
}
|
||||||
|
if (!runner.hasOption(RedisRunner.REDIS_OPTIONS.BIND)) {
|
||||||
|
runner.bind("127.0.0.1");
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RedisRunner.RedisProcess> run() throws IOException, InterruptedException, RedisRunner.FailedToStartRedisException {
|
||||||
|
ArrayList<RedisRunner.RedisProcess> processes = new ArrayList<>();
|
||||||
|
for (RedisRunner runner : nodes.keySet()) {
|
||||||
|
List<String> options = getClusterConfig(runner);
|
||||||
|
String confFile = runner.defaultDir() + File.pathSeparator + nodes.get(runner) + ".conf";
|
||||||
|
System.out.println("WRITING CONFIG: for " + nodes.get(runner));
|
||||||
|
try (PrintWriter printer = new PrintWriter(new FileWriter(confFile))) {
|
||||||
|
options.stream().forEach((line) -> {
|
||||||
|
printer.println(line);
|
||||||
|
System.out.println(line);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
processes.add(runner.clusterConfigFile(confFile).run());
|
||||||
|
}
|
||||||
|
Thread.sleep(1000);
|
||||||
|
for (RedisRunner.RedisProcess process : processes) {
|
||||||
|
if (!process.isAlive()) {
|
||||||
|
throw new RedisRunner.FailedToStartRedisException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return processes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getClusterConfig(RedisRunner runner) {
|
||||||
|
String me = runner.getInitialBindAddr() + ":" + runner.getPort();
|
||||||
|
List<String> nodeConfig = new ArrayList<>();
|
||||||
|
int c = 0;
|
||||||
|
for (RedisRunner node : nodes.keySet()) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String nodeAddr = node.getInitialBindAddr() + ":" + node.getPort();
|
||||||
|
sb.append(nodes.get(node)).append(" ");
|
||||||
|
sb.append(nodeAddr).append(" ");
|
||||||
|
sb.append(me.equals(nodeAddr)
|
||||||
|
? "myself,"
|
||||||
|
: "").append("master -").append(" ");
|
||||||
|
sb.append("0").append(" ");
|
||||||
|
sb.append(me.equals(nodeAddr)
|
||||||
|
? "0"
|
||||||
|
: "1").append(" ");
|
||||||
|
sb.append(c + 1).append(" ");
|
||||||
|
sb.append("connected ");
|
||||||
|
sb.append(getSlots(c, nodes.size()));
|
||||||
|
c++;
|
||||||
|
nodeConfig.add(sb.toString());
|
||||||
|
}
|
||||||
|
nodeConfig.add("vars currentEpoch 0 lastVoteEpoch 0");
|
||||||
|
return nodeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSlots(int index, int groupNum) {
|
||||||
|
final double t = 16383;
|
||||||
|
int start = index == 0 ? 0 : (int) (t / groupNum * index);
|
||||||
|
int end = index == groupNum - 1 ? (int) t : (int) (t / groupNum * (index + 1)) - 1;
|
||||||
|
return start + "-" + end;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRandomId() {
|
||||||
|
final SecureRandom r = new SecureRandom();
|
||||||
|
return new BigInteger(160, r).toString(16);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package org.redisson.misc;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.redisson.cache.Cache;
|
||||||
|
import org.redisson.cache.SoftCacheMap;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class SoftCacheMapTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMaxIdleTimeEviction() throws InterruptedException {
|
||||||
|
Cache<Integer, Integer> map = new SoftCacheMap<Integer, Integer>(0, 0);
|
||||||
|
map.put(1, 0, 0, TimeUnit.MILLISECONDS, 400, TimeUnit.MILLISECONDS);
|
||||||
|
assertThat(map.get(1)).isEqualTo(0);
|
||||||
|
Thread.sleep(200);
|
||||||
|
assertThat(map.get(1)).isEqualTo(0);
|
||||||
|
Thread.sleep(200);
|
||||||
|
assertThat(map.get(1)).isEqualTo(0);
|
||||||
|
Thread.sleep(200);
|
||||||
|
assertThat(map.get(1)).isEqualTo(0);
|
||||||
|
Thread.sleep(410);
|
||||||
|
assertThat(map.keySet()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTTLEviction() throws InterruptedException {
|
||||||
|
Cache<Integer, Integer> map = new SoftCacheMap<Integer, Integer>(0, 0);
|
||||||
|
map.put(1, 0, 500, TimeUnit.MILLISECONDS, 0, TimeUnit.MILLISECONDS);
|
||||||
|
assertThat(map.get(1)).isEqualTo(0);
|
||||||
|
Thread.sleep(100);
|
||||||
|
assertThat(map.get(1)).isEqualTo(0);
|
||||||
|
assertThat(map.keySet()).containsOnly(1);
|
||||||
|
Thread.sleep(500);
|
||||||
|
assertThat(map.keySet()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSizeEviction() {
|
||||||
|
Cache<Integer, Integer> map = new SoftCacheMap<Integer, Integer>(0, 0);
|
||||||
|
map.put(1, 0);
|
||||||
|
map.put(2, 0);
|
||||||
|
|
||||||
|
assertThat(map.keySet()).containsOnly(1, 2);
|
||||||
|
map.put(3, 0);
|
||||||
|
map.put(4, 0);
|
||||||
|
|
||||||
|
assertThat(map.keySet()).containsOnly(1, 2, 3, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test requires using -XX:SoftRefLRUPolicyMSPerMB=0 to pass
|
||||||
|
@Test
|
||||||
|
public void testSoftReferences() {
|
||||||
|
Cache<Integer, Integer> map = new SoftCacheMap<Integer, Integer>(0, 0);
|
||||||
|
for(int i=0;i<100000;i++) {
|
||||||
|
map.put(i, new Integer(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(map.values().stream().filter(Objects::nonNull).count()).isEqualTo(100000);
|
||||||
|
System.gc();
|
||||||
|
assertThat(map.values().stream().filter(Objects::nonNull).count()).isZero();
|
||||||
|
assertThat(map.values().size()).isZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,282 @@
|
|||||||
|
package org.redisson.spring.support;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
import org.junit.runners.Parameterized.Parameter;
|
||||||
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
import org.redisson.BaseTest;
|
||||||
|
import org.redisson.RedisRunner;
|
||||||
|
import org.redisson.RedissonFairLock;
|
||||||
|
import org.redisson.RedissonLiveObjectServiceTest.TestREntity;
|
||||||
|
import org.redisson.RedissonMultiLock;
|
||||||
|
import org.redisson.RedissonReadLock;
|
||||||
|
import org.redisson.RedissonRedLock;
|
||||||
|
import org.redisson.RedissonRuntimeEnvironment;
|
||||||
|
import org.redisson.RedissonWriteLock;
|
||||||
|
import org.redisson.api.LocalCachedMapOptions;
|
||||||
|
import org.redisson.api.RAtomicDouble;
|
||||||
|
import org.redisson.api.RAtomicLong;
|
||||||
|
import org.redisson.api.RBinaryStream;
|
||||||
|
import org.redisson.api.RBitSet;
|
||||||
|
import org.redisson.api.RBlockingDeque;
|
||||||
|
import org.redisson.api.RBlockingFairQueue;
|
||||||
|
import org.redisson.api.RBlockingQueue;
|
||||||
|
import org.redisson.api.RBloomFilter;
|
||||||
|
import org.redisson.api.RBoundedBlockingQueue;
|
||||||
|
import org.redisson.api.RBucket;
|
||||||
|
import org.redisson.api.RBuckets;
|
||||||
|
import org.redisson.api.RCountDownLatch;
|
||||||
|
import org.redisson.api.RDelayedQueue;
|
||||||
|
import org.redisson.api.RDeque;
|
||||||
|
import org.redisson.api.RExecutorService;
|
||||||
|
import org.redisson.api.RGeo;
|
||||||
|
import org.redisson.api.RHyperLogLog;
|
||||||
|
import org.redisson.api.RKeys;
|
||||||
|
import org.redisson.api.RLexSortedSet;
|
||||||
|
import org.redisson.api.RList;
|
||||||
|
import org.redisson.api.RListMultimap;
|
||||||
|
import org.redisson.api.RLiveObject;
|
||||||
|
import org.redisson.api.RLiveObjectService;
|
||||||
|
import org.redisson.api.RLocalCachedMap;
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
import org.redisson.api.RMap;
|
||||||
|
import org.redisson.api.RMapCache;
|
||||||
|
import org.redisson.api.RObject;
|
||||||
|
import org.redisson.api.RPatternTopic;
|
||||||
|
import org.redisson.api.RPermitExpirableSemaphore;
|
||||||
|
import org.redisson.api.RPriorityDeque;
|
||||||
|
import org.redisson.api.RPriorityQueue;
|
||||||
|
import org.redisson.api.RQueue;
|
||||||
|
import org.redisson.api.RReadWriteLock;
|
||||||
|
import org.redisson.api.RRemoteService;
|
||||||
|
import org.redisson.api.RScoredSortedSet;
|
||||||
|
import org.redisson.api.RScript;
|
||||||
|
import org.redisson.api.RSemaphore;
|
||||||
|
import org.redisson.api.RSet;
|
||||||
|
import org.redisson.api.RSetCache;
|
||||||
|
import org.redisson.api.RSetMultimap;
|
||||||
|
import org.redisson.api.RSetMultimapCache;
|
||||||
|
import org.redisson.api.RSortedSet;
|
||||||
|
import org.redisson.api.RTopic;
|
||||||
|
import org.redisson.api.RemoteInvocationOptions;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
|
public class SpringNamespaceObjectTest extends BaseTest {
|
||||||
|
|
||||||
|
private static ApplicationContext context;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupClass() throws Exception {
|
||||||
|
if (!RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
startContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void shutDownClass() {
|
||||||
|
if (!RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
stopContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
if (RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
startContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void shutDown() {
|
||||||
|
if (RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
stopContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean flushBetweenTests() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startContext() {
|
||||||
|
TestREntity entity = new TestREntity("live-object");
|
||||||
|
entity.setValue("1");
|
||||||
|
defaultRedisson.getLiveObjectService().merge(entity);
|
||||||
|
entity = new TestREntity("live-object-ext");
|
||||||
|
entity.setValue("1");
|
||||||
|
defaultRedisson.getLiveObjectService().merge(entity);
|
||||||
|
|
||||||
|
System.setProperty("redisAddress", RedisRunner.getDefaultRedisServerBindAddressAndPort());
|
||||||
|
context = new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/redisson_objects.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopContext() {
|
||||||
|
((ConfigurableApplicationContext) context).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parameters(name = "{index}: key=[{0}], class=[{1}], parent=[{2}]")
|
||||||
|
public static Collection<Object[]> tests() {
|
||||||
|
return Arrays.asList(new Object[][]{
|
||||||
|
{"binary-stream", RBinaryStream.class, null},
|
||||||
|
{"geo", RGeo.class, null},
|
||||||
|
{"set-cache", RSetCache.class, null},
|
||||||
|
{"map-cache", RMapCache.class, null},
|
||||||
|
{"bucket", RBucket.class, null},
|
||||||
|
{"buckets", RBuckets.class, null},
|
||||||
|
{"hyper-log-log", RHyperLogLog.class, null},
|
||||||
|
{"list", RList.class, null},
|
||||||
|
{"list-multimap", RListMultimap.class, null},
|
||||||
|
{"local-cached-map", RLocalCachedMap.class, null},
|
||||||
|
{"local-options", LocalCachedMapOptions.class, null},
|
||||||
|
{"map", RMap.class, null},
|
||||||
|
{"set-multimap", RSetMultimap.class, null},
|
||||||
|
{"set-multimap-cache", RSetMultimapCache.class, null},
|
||||||
|
{"semaphore", RSemaphore.class, null},
|
||||||
|
{"permit-expirable-semaphore", RPermitExpirableSemaphore.class, null},
|
||||||
|
{"lock", RLock.class, null},
|
||||||
|
{"fair-lock", RedissonFairLock.class, null},
|
||||||
|
{"read-write-lock", RReadWriteLock.class, null},
|
||||||
|
{"read-lock", RedissonReadLock.class, "read-write-lock"},
|
||||||
|
{"write-lock", RedissonWriteLock.class, "read-write-lock"},
|
||||||
|
{"multi-lock", RedissonMultiLock.class, null},
|
||||||
|
{"lock-1", RLock.class, null},
|
||||||
|
{"fair-lock-1", RedissonFairLock.class, null},
|
||||||
|
{"read-lock-1", RedissonReadLock.class, "read-write-lock"},
|
||||||
|
{"write-lock-1", RedissonWriteLock.class, "read-write-lock"},
|
||||||
|
{"red-lock", RedissonRedLock.class, null},
|
||||||
|
{"lock-2", RLock.class, null},
|
||||||
|
{"fair-lock-2", RedissonFairLock.class, null},
|
||||||
|
{"read-lock-2", RedissonReadLock.class, "read-write-lock"},
|
||||||
|
{"write-lock-2", RedissonWriteLock.class, "read-write-lock"},
|
||||||
|
{"set", RSet.class, null},
|
||||||
|
{"sorted-set", RSortedSet.class, null},
|
||||||
|
{"scored-sorted-set", RScoredSortedSet.class, null},
|
||||||
|
{"lex-sorted-set", RLexSortedSet.class, null},
|
||||||
|
{"topic", RTopic.class, null},
|
||||||
|
{"pattern-topic", RPatternTopic.class, null},
|
||||||
|
{"blocking-fair-queue", RBlockingFairQueue.class, null},
|
||||||
|
{"queue", RQueue.class, null},
|
||||||
|
{"delayed-queue", RDelayedQueue.class, "queue"},
|
||||||
|
{"priority-queue", RPriorityQueue.class, null},
|
||||||
|
{"priority-deque", RPriorityDeque.class, null},
|
||||||
|
{"blocking-queue", RBlockingQueue.class, null},
|
||||||
|
{"bounded-blocking-queue", RBoundedBlockingQueue.class, null},
|
||||||
|
{"deque", RDeque.class, null},
|
||||||
|
{"blocking-deque", RBlockingDeque.class, null},
|
||||||
|
{"atomic-long", RAtomicLong.class, null},
|
||||||
|
{"atomic-double", RAtomicDouble.class, null},
|
||||||
|
{"count-down-latch", RCountDownLatch.class, null},
|
||||||
|
{"bit-set", RBitSet.class, null},
|
||||||
|
{"bloom-filter", RBloomFilter.class, null},
|
||||||
|
{"script", RScript.class, null},
|
||||||
|
{"executor-service", RExecutorService.class, null},
|
||||||
|
{"remote-service", RRemoteService.class, null},
|
||||||
|
{"rpc-client", org.redisson.RedissonRemoteServiceTest.RemoteInterface.class, null},
|
||||||
|
{"options", RemoteInvocationOptions.class, null},
|
||||||
|
{"keys", RKeys.class, null},
|
||||||
|
{"live-object-service", RLiveObjectService.class, null},
|
||||||
|
{"live-object", RLiveObject.class, null},
|
||||||
|
{"binary-stream-ext", RBinaryStream.class, null},
|
||||||
|
{"geo-ext", RGeo.class, null},
|
||||||
|
{"set-cache-ext", RSetCache.class, null},
|
||||||
|
{"map-cache-ext", RMapCache.class, null},
|
||||||
|
{"bucket-ext", RBucket.class, null},
|
||||||
|
{"buckets-ext", RBuckets.class, null},
|
||||||
|
{"hyper-log-log-ext", RHyperLogLog.class, null},
|
||||||
|
{"list-ext", RList.class, null},
|
||||||
|
{"list-multimap-ext", RListMultimap.class, null},
|
||||||
|
{"local-cached-map-ext", RLocalCachedMap.class, null},
|
||||||
|
{"local-options-ext", LocalCachedMapOptions.class, null},
|
||||||
|
{"map-ext", RMap.class, null},
|
||||||
|
{"set-multimap-ext", RSetMultimap.class, null},
|
||||||
|
{"set-multimap-cache-ext", RSetMultimapCache.class, null},
|
||||||
|
{"semaphore-ext", RSemaphore.class, null},
|
||||||
|
{"permit-expirable-semaphore-ext", RPermitExpirableSemaphore.class, null},
|
||||||
|
{"lock-ext", RLock.class, null},
|
||||||
|
{"fair-lock-ext", RedissonFairLock.class, null},
|
||||||
|
{"read-write-lock-ext", RReadWriteLock.class, null},
|
||||||
|
{"read-lock-ext", RedissonReadLock.class, "read-write-lock-ext"},
|
||||||
|
{"write-lock-ext", RedissonWriteLock.class, "read-write-lock-ext"},
|
||||||
|
{"multi-lock-ext", RedissonMultiLock.class, null},
|
||||||
|
{"lock-1-ext", RLock.class, null},
|
||||||
|
{"fair-lock-1-ext", RedissonFairLock.class, null},
|
||||||
|
{"read-lock-1-ext", RedissonReadLock.class, "read-write-lock-ext"},
|
||||||
|
{"write-lock-1-ext", RedissonWriteLock.class, "read-write-lock-ext"},
|
||||||
|
{"red-lock-ext", RedissonRedLock.class, null},
|
||||||
|
{"lock-2-ext", RLock.class, null},
|
||||||
|
{"fair-lock-2-ext", RedissonFairLock.class, null},
|
||||||
|
{"read-lock-2-ext", RedissonReadLock.class, "read-write-lock-ext"},
|
||||||
|
{"write-lock-2-ext", RedissonWriteLock.class, "read-write-lock-ext"},
|
||||||
|
{"set-ext", RSet.class, null},
|
||||||
|
{"sorted-set-ext", RSortedSet.class, null},
|
||||||
|
{"scored-sorted-set-ext", RScoredSortedSet.class, null},
|
||||||
|
{"lex-sorted-set-ext", RLexSortedSet.class, null},
|
||||||
|
{"topic-ext", RTopic.class, null},
|
||||||
|
{"pattern-topic-ext", RPatternTopic.class, null},
|
||||||
|
{"blocking-fair-queue-ext", RBlockingFairQueue.class, null},
|
||||||
|
{"queue-ext", RQueue.class, null},
|
||||||
|
{"delayed-queue-ext", RDelayedQueue.class, "queue-ext"},
|
||||||
|
{"priority-queue-ext", RPriorityQueue.class, null},
|
||||||
|
{"priority-deque-ext", RPriorityDeque.class, null},
|
||||||
|
{"blocking-queue-ext", RBlockingQueue.class, null},
|
||||||
|
{"bounded-blocking-queue-ext", RBoundedBlockingQueue.class, null},
|
||||||
|
{"deque-ext", RDeque.class, null},
|
||||||
|
{"blocking-deque-ext", RBlockingDeque.class, null},
|
||||||
|
{"atomic-long-ext", RAtomicLong.class, null},
|
||||||
|
{"atomic-double-ext", RAtomicDouble.class, null},
|
||||||
|
{"count-down-latch-ext", RCountDownLatch.class, null},
|
||||||
|
{"bit-set-ext", RBitSet.class, null},
|
||||||
|
{"bloom-filter-ext", RBloomFilter.class, null},
|
||||||
|
{"script-ext", RScript.class, null},
|
||||||
|
{"executor-service-ext", RExecutorService.class, null},
|
||||||
|
{"remote-service-ext", RRemoteService.class, null},
|
||||||
|
{"rpc-client-ext", org.redisson.RedissonRemoteServiceTest.RemoteInterface.class, null},
|
||||||
|
{"options-ext", RemoteInvocationOptions.class, null},
|
||||||
|
{"keys-ext", RKeys.class, null},
|
||||||
|
{"live-object-service-ext", RLiveObjectService.class, null},
|
||||||
|
{"live-object-ext", RLiveObject.class, null},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parameter
|
||||||
|
public String key;
|
||||||
|
|
||||||
|
@Parameter(1)
|
||||||
|
public Class cls;
|
||||||
|
|
||||||
|
@Parameter(2)
|
||||||
|
public String parentKey;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRObjects() {
|
||||||
|
Object bean = context.getBean(key);
|
||||||
|
assertTrue(cls.isInstance(bean));
|
||||||
|
if (RObject.class.isAssignableFrom(cls)) {
|
||||||
|
assertEquals(parentKey == null ? key : parentKey, RObject.class.cast(bean).getName());
|
||||||
|
}
|
||||||
|
if (RTopic.class.isAssignableFrom(cls)) {
|
||||||
|
assertEquals(key, RTopic.class.cast(bean).getChannelNames().get(0));
|
||||||
|
}
|
||||||
|
if (RPatternTopic.class.isAssignableFrom(cls)) {
|
||||||
|
assertEquals(key, RPatternTopic.class.cast(bean).getPatternNames().get(0));
|
||||||
|
}
|
||||||
|
if (RLiveObject.class.isAssignableFrom(cls)) {
|
||||||
|
assertEquals(key, RLiveObject.class.cast(bean).getLiveObjectId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,368 @@
|
|||||||
|
package org.redisson.spring.support;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.redisson.BaseTest;
|
||||||
|
import org.redisson.ClusterRunner;
|
||||||
|
import org.redisson.RedisRunner;
|
||||||
|
import org.redisson.Redisson;
|
||||||
|
import org.redisson.RedissonRuntimeEnvironment;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.redisson.client.RedisClient;
|
||||||
|
import org.redisson.client.RedisConnection;
|
||||||
|
import org.redisson.codec.MsgPackJacksonCodec;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class SpringNamespaceTest extends BaseTest {
|
||||||
|
|
||||||
|
private static ApplicationContext context;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupClass() throws Exception {
|
||||||
|
if (!RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
startContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void shutDownClass() throws Exception {
|
||||||
|
if (!RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
stopContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
if (RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
startContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void shutDown() throws Exception {
|
||||||
|
if (RedissonRuntimeEnvironment.isTravis) {
|
||||||
|
stopContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startContext() throws Exception {
|
||||||
|
System.setProperty("redisAddress", RedisRunner.getDefaultRedisServerBindAddressAndPort());
|
||||||
|
|
||||||
|
//Needs a instance running on the default port, launch it if there isn't one already
|
||||||
|
if (RedisRunner.isFreePort(6379)) {
|
||||||
|
new RedisRunner()
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
RedisRunner.RedisProcess slave1 = new RedisRunner()
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.randomPort()
|
||||||
|
.slaveof(
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort())
|
||||||
|
.run();
|
||||||
|
System.setProperty("slave1Address", slave1.getRedisServerAddressAndPort());
|
||||||
|
|
||||||
|
RedisRunner.RedisProcess slave2 = new RedisRunner()
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.randomPort()
|
||||||
|
.slaveof(
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort())
|
||||||
|
.run();
|
||||||
|
System.setProperty("slave2Address", slave2.getRedisServerAddressAndPort());
|
||||||
|
|
||||||
|
RedisRunner.RedisProcess sentinel1 = new RedisRunner()
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.randomPort()
|
||||||
|
.sentinel()
|
||||||
|
.sentinelMonitor(
|
||||||
|
"myMaster",
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort(),
|
||||||
|
2).run();
|
||||||
|
System.setProperty("sentinel1Address", sentinel1.getRedisServerAddressAndPort());
|
||||||
|
|
||||||
|
RedisRunner.RedisProcess sentinel2 = new RedisRunner()
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.randomPort()
|
||||||
|
.sentinel()
|
||||||
|
.sentinelMonitor(
|
||||||
|
"myMaster",
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort(),
|
||||||
|
2).run();
|
||||||
|
System.setProperty("sentinel2Address", sentinel2.getRedisServerAddressAndPort());
|
||||||
|
|
||||||
|
RedisRunner.RedisProcess sentinel3 = new RedisRunner()
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.randomPort()
|
||||||
|
.sentinel()
|
||||||
|
.sentinelMonitor(
|
||||||
|
"myMaster",
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerBindAddress(),
|
||||||
|
RedisRunner.getDefaultRedisServerInstance().getRedisServerPort(),
|
||||||
|
2).run();
|
||||||
|
System.setProperty("sentinel3Address", sentinel3.getRedisServerAddressAndPort());
|
||||||
|
|
||||||
|
ClusterRunner clusterRunner = new ClusterRunner()
|
||||||
|
.addNode(new RedisRunner().randomPort().randomDir().nosave())
|
||||||
|
.addNode(new RedisRunner().randomPort().randomDir().nosave())
|
||||||
|
.addNode(new RedisRunner().randomPort().randomDir().nosave());
|
||||||
|
List<RedisRunner.RedisProcess> nodes = clusterRunner.run();
|
||||||
|
nodes.stream().forEach((node) -> {
|
||||||
|
System.setProperty("node" + (nodes.indexOf(node) + 1) + "Address", node.getRedisServerAddressAndPort());
|
||||||
|
});
|
||||||
|
|
||||||
|
context = new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/namespace.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopContext() throws Exception {
|
||||||
|
((ConfigurableApplicationContext) context).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AutowireRedisson {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("redisson1")
|
||||||
|
private Redisson redisson1;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("redisson2")
|
||||||
|
private RedissonClient redisson2;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("redisson3")
|
||||||
|
private Redisson redisson3;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("redisson4")
|
||||||
|
private RedissonClient redisson4;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("myRedisson1")
|
||||||
|
private Redisson redisson5;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("myRedisson2")
|
||||||
|
private Redisson redisson6;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("qualifier1")
|
||||||
|
private RedissonClient redisson7;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("qualifier2")
|
||||||
|
private RedissonClient redisson8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson1
|
||||||
|
*/
|
||||||
|
public Redisson getRedisson1() {
|
||||||
|
return redisson1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson1 the redisson1 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson1(Redisson redisson1) {
|
||||||
|
this.redisson1 = redisson1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson2
|
||||||
|
*/
|
||||||
|
public RedissonClient getRedisson2() {
|
||||||
|
return redisson2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson2 the redisson2 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson2(RedissonClient redisson2) {
|
||||||
|
this.redisson2 = redisson2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson3
|
||||||
|
*/
|
||||||
|
public Redisson getRedisson3() {
|
||||||
|
return redisson3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson3 the redisson3 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson3(Redisson redisson3) {
|
||||||
|
this.redisson3 = redisson3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson4
|
||||||
|
*/
|
||||||
|
public RedissonClient getRedisson4() {
|
||||||
|
return redisson4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson4 the redisson4 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson4(RedissonClient redisson4) {
|
||||||
|
this.redisson4 = redisson4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson5
|
||||||
|
*/
|
||||||
|
public Redisson getRedisson5() {
|
||||||
|
return redisson5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson5 the redisson5 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson5(Redisson redisson5) {
|
||||||
|
this.redisson5 = redisson5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson6
|
||||||
|
*/
|
||||||
|
public Redisson getRedisson6() {
|
||||||
|
return redisson6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson6 the redisson6 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson6(Redisson redisson6) {
|
||||||
|
this.redisson6 = redisson6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson7
|
||||||
|
*/
|
||||||
|
public RedissonClient getRedisson7() {
|
||||||
|
return redisson7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson7 the redisson7 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson7(RedissonClient redisson7) {
|
||||||
|
this.redisson7 = redisson7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisson8
|
||||||
|
*/
|
||||||
|
public RedissonClient getRedisson8() {
|
||||||
|
return redisson8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisson8 the redisson8 to set
|
||||||
|
*/
|
||||||
|
public void setRedisson8(RedissonClient redisson8) {
|
||||||
|
this.redisson8 = redisson8;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNamespace() {
|
||||||
|
Object bean = context.getBean("myRedisson1");
|
||||||
|
assertTrue(bean instanceof Redisson);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAlias() {
|
||||||
|
Object origin = context.getBean("myRedisson1");
|
||||||
|
assertTrue(origin instanceof Redisson);
|
||||||
|
Object bean = context.getBean("redisson1");
|
||||||
|
assertTrue(bean instanceof Redisson);
|
||||||
|
assertEquals(origin, bean);
|
||||||
|
bean = context.getBean("redisson2");
|
||||||
|
assertTrue(bean instanceof Redisson);
|
||||||
|
assertEquals(origin, bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAutowire() {
|
||||||
|
AutowireRedisson bean = context.getAutowireCapableBeanFactory().getBean(AutowireRedisson.class);
|
||||||
|
assertNotNull(bean.getRedisson1());
|
||||||
|
assertNotNull(bean.getRedisson2());
|
||||||
|
assertNotNull(bean.getRedisson3());
|
||||||
|
assertNotNull(bean.getRedisson4());
|
||||||
|
assertNotNull(bean.getRedisson5());
|
||||||
|
assertNotNull(bean.getRedisson6());
|
||||||
|
assertNotNull(bean.getRedisson7());
|
||||||
|
assertNotNull(bean.getRedisson8());
|
||||||
|
assertEquals(bean.getRedisson1(), bean.getRedisson2());
|
||||||
|
assertEquals(bean.getRedisson1(), bean.getRedisson5());
|
||||||
|
assertNotEquals(bean.getRedisson1(), bean.getRedisson7());
|
||||||
|
assertNotEquals(bean.getRedisson1(), bean.getRedisson8());
|
||||||
|
assertEquals(bean.getRedisson3(), bean.getRedisson4());
|
||||||
|
assertEquals(bean.getRedisson3(), bean.getRedisson6());
|
||||||
|
assertNotEquals(bean.getRedisson3(), bean.getRedisson7());
|
||||||
|
assertNotEquals(bean.getRedisson3(), bean.getRedisson8());
|
||||||
|
assertNotEquals(bean.getRedisson7(), bean.getRedisson8());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBeanRef() {
|
||||||
|
AutowireRedisson bean = context.getAutowireCapableBeanFactory().getBean(AutowireRedisson.class);
|
||||||
|
assertTrue(bean.getRedisson1().getConfig().getCodec() instanceof MsgPackJacksonCodec);
|
||||||
|
assertFalse(bean.getRedisson3().getConfig().getCodec() instanceof MsgPackJacksonCodec);
|
||||||
|
assertFalse(bean.getRedisson7().getConfig().getCodec() instanceof MsgPackJacksonCodec);
|
||||||
|
assertFalse(bean.getRedisson8().getConfig().getCodec() instanceof MsgPackJacksonCodec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AutowireRedis {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisClient redisClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the redisClient
|
||||||
|
*/
|
||||||
|
public RedisClient getRedisClient() {
|
||||||
|
return redisClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param redisClient the redisClient to set
|
||||||
|
*/
|
||||||
|
public void setRedisClient(RedisClient redisClient) {
|
||||||
|
this.redisClient = redisClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAutowireRedis() {
|
||||||
|
AutowireRedis bean = context.getAutowireCapableBeanFactory().getBean(AutowireRedis.class);
|
||||||
|
RedisConnection connection = bean.getRedisClient().connect();
|
||||||
|
assertTrue(connection.isActive());
|
||||||
|
connection.closeAsync().awaitUninterruptibly();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,195 @@
|
|||||||
|
package org.redisson.spring.support;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.redisson.ClusterRunner;
|
||||||
|
import org.redisson.RedisRunner;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Rui Gu (https://github.com/jackygurui)
|
||||||
|
*/
|
||||||
|
public class SpringNamespaceWikiTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingle() throws Exception {
|
||||||
|
RedisRunner.RedisProcess run = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.run();
|
||||||
|
try {
|
||||||
|
((ConfigurableApplicationContext)
|
||||||
|
new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/namespace_wiki_single.xml"))
|
||||||
|
.close();
|
||||||
|
} finally {
|
||||||
|
run.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMasterSlave() throws Exception {
|
||||||
|
RedisRunner.RedisProcess master = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess slave1 = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.masterauth("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6380)
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.slaveof("127.0.0.1", 6379)
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess slave2 = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.masterauth("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6381)
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.slaveof("127.0.0.1", 6379)
|
||||||
|
.run();
|
||||||
|
try {
|
||||||
|
((ConfigurableApplicationContext)
|
||||||
|
new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/namespace_wiki_master_slave.xml"))
|
||||||
|
.close();
|
||||||
|
} finally {
|
||||||
|
master.stop();
|
||||||
|
slave1.stop();
|
||||||
|
slave2.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSentinel() throws Exception {
|
||||||
|
RedisRunner.RedisProcess master = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess slave1 = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.masterauth("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6380)
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.slaveof("127.0.0.1", 6379)
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess slave2 = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.masterauth("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6381)
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.slaveof("127.0.0.1", 6379)
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess sentinel1 = new RedisRunner()
|
||||||
|
// .requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.port(26379)
|
||||||
|
.sentinel()
|
||||||
|
.sentinelMonitor("myMaster", "127.0.0.1", 6379, 2)
|
||||||
|
.sentinelAuthPass("myMaster", "do_not_use_if_it_is_not_set")
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess sentinel2 = new RedisRunner()
|
||||||
|
// .requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.port(26380)
|
||||||
|
.sentinel()
|
||||||
|
.sentinelMonitor("myMaster", "127.0.0.1", 6379, 2)
|
||||||
|
.sentinelAuthPass("myMaster", "do_not_use_if_it_is_not_set")
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess sentinel3 = new RedisRunner()
|
||||||
|
// .requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.port(26381)
|
||||||
|
.sentinel()
|
||||||
|
.sentinelMonitor("myMaster", "127.0.0.1", 6379, 2)
|
||||||
|
.sentinelAuthPass("myMaster", "do_not_use_if_it_is_not_set")
|
||||||
|
.run();
|
||||||
|
try {
|
||||||
|
((ConfigurableApplicationContext)
|
||||||
|
new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/namespace_wiki_sentinel.xml"))
|
||||||
|
.close();
|
||||||
|
} finally {
|
||||||
|
master.stop();
|
||||||
|
slave1.stop();
|
||||||
|
slave2.stop();
|
||||||
|
sentinel1.stop();
|
||||||
|
sentinel2.stop();
|
||||||
|
sentinel3.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReplicated() throws Exception {
|
||||||
|
RedisRunner.RedisProcess master = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess slave1 = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.masterauth("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6380)
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.slaveof("127.0.0.1", 6379)
|
||||||
|
.run();
|
||||||
|
RedisRunner.RedisProcess slave2 = new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.masterauth("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6381)
|
||||||
|
.nosave()
|
||||||
|
.randomDir()
|
||||||
|
.slaveof("127.0.0.1", 6379)
|
||||||
|
.run();
|
||||||
|
try {
|
||||||
|
((ConfigurableApplicationContext)
|
||||||
|
new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/namespace_wiki_replicated.xml"))
|
||||||
|
.close();
|
||||||
|
} finally {
|
||||||
|
master.stop();
|
||||||
|
slave1.stop();
|
||||||
|
slave2.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCluster() throws Exception {
|
||||||
|
ClusterRunner clusterRunner = new ClusterRunner()
|
||||||
|
.addNode(new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6379)
|
||||||
|
.randomDir()
|
||||||
|
.nosave())
|
||||||
|
.addNode(new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6380)
|
||||||
|
.randomDir()
|
||||||
|
.nosave())
|
||||||
|
.addNode(new RedisRunner()
|
||||||
|
.requirepass("do_not_use_if_it_is_not_set")
|
||||||
|
.port(6381)
|
||||||
|
.randomDir()
|
||||||
|
.nosave());
|
||||||
|
List<RedisRunner.RedisProcess> nodes = clusterRunner.run();
|
||||||
|
|
||||||
|
try {
|
||||||
|
((ConfigurableApplicationContext)
|
||||||
|
new ClassPathXmlApplicationContext("classpath:org/redisson/spring/support/namespace_wiki_cluster.xml"))
|
||||||
|
.close();
|
||||||
|
} finally {
|
||||||
|
for (RedisRunner.RedisProcess node : nodes) {
|
||||||
|
node.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xmlns:redisson="http://redisson.org/schema/redisson"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
|
||||||
|
http://redisson.org/schema/redisson classpath:org/redisson/spring/support/redisson-1.0.xsd
|
||||||
|
">
|
||||||
|
<context:annotation-config />
|
||||||
|
<context:property-placeholder system-properties-mode="OVERRIDE"/>
|
||||||
|
|
||||||
|
<redisson:client id="myRedisson1" name="redisson1,redisson2" codec-ref="myCodec" >
|
||||||
|
<redisson:single-server address="${redisAddress}" client-name="1"/>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<redisson:client id="myRedisson2" name="redisson3,redisson4">
|
||||||
|
<redisson:single-server address="${redisAddress}" client-name="2"/>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<redisson:client>
|
||||||
|
<qualifier value="qualifier1"/>
|
||||||
|
<redisson:single-server address="${redisAddress}" client-name="3"/>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<redisson:client>
|
||||||
|
<qualifier value="qualifier2"/>
|
||||||
|
<redisson:single-server address="${redisAddress}" client-name="4"/>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<!-- Minimal requirement for redisson client-->
|
||||||
|
<redisson:client>
|
||||||
|
<!-- Use default address "127.0.0.1:6379" -->
|
||||||
|
<redisson:single-server />
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<redisson:client>
|
||||||
|
<redisson:sentinel-servers master-name="myMaster">
|
||||||
|
<redisson:sentinel-address value="${sentinel1Address}" />
|
||||||
|
<redisson:sentinel-address value="${sentinel2Address}" />
|
||||||
|
<redisson:sentinel-address value="${sentinel3Address}" />
|
||||||
|
</redisson:sentinel-servers>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<redisson:client>
|
||||||
|
<redisson:master-slave-servers master-address="${redisAddress}">
|
||||||
|
<redisson:slave-address value="${slave1Address}" />
|
||||||
|
<redisson:slave-address value="${slave2Address}" />
|
||||||
|
</redisson:master-slave-servers>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<redisson:client>
|
||||||
|
<redisson:cluster-servers>
|
||||||
|
<redisson:node-address value="${node1Address}" />
|
||||||
|
<redisson:node-address value="${node2Address}" />
|
||||||
|
<redisson:node-address value="${node3Address}" />
|
||||||
|
</redisson:cluster-servers>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<redisson:client>
|
||||||
|
<redisson:replicated-servers read-mode="MASTER_SLAVE" >
|
||||||
|
<redisson:node-address value="${redisAddress}" />
|
||||||
|
<redisson:node-address value="${slave1Address}" />
|
||||||
|
<redisson:node-address value="${slave2Address}" />
|
||||||
|
</redisson:replicated-servers>
|
||||||
|
</redisson:client>
|
||||||
|
|
||||||
|
<!-- Minimal requirement for redis client-->
|
||||||
|
<!-- Use default host 127.0.0.1 and port 6379 -->
|
||||||
|
<redisson:redis />
|
||||||
|
|
||||||
|
<bean id="myCodec" class="org.redisson.codec.MsgPackJacksonCodec" />
|
||||||
|
|
||||||
|
<bean class="org.redisson.spring.support.SpringNamespaceTest.AutowireRedisson" />
|
||||||
|
<bean class="org.redisson.spring.support.SpringNamespaceTest.AutowireRedis" />
|
||||||
|
</beans>
|
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xmlns:redisson="http://redisson.org/schema/redisson"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
|
||||||
|
http://redisson.org/schema/redisson classpath:org/redisson/spring/support/redisson-1.0.xsd
|
||||||
|
">
|
||||||
|
<bean id="myCodec" class="org.redisson.codec.MsgPackJacksonCodec"/>
|
||||||
|
<bean id="myCodecProvider" class="org.redisson.codec.DefaultCodecProvider"/>
|
||||||
|
<bean id="myResolverProvider" class="org.redisson.liveobject.provider.DefaultResolverProvider"/>
|
||||||
|
<bean id="myExecutor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||||
|
<property name="staticMethod" value="java.util.concurrent.Executors.newFixedThreadPool"/>
|
||||||
|
<property name="arguments" value="8"/>
|
||||||
|
</bean>
|
||||||
|
<bean id="myEventLoopGroup" class="io.netty.channel.nio.NioEventLoopGroup"/>
|
||||||
|
<bean id="myLoadBalancer" class="org.redisson.connection.balancer.RoundRobinLoadBalancer"/>
|
||||||
|
|
||||||
|
<redisson:client
|
||||||
|
id="redisson"
|
||||||
|
name="redisson1,redisson2"
|
||||||
|
threads="0"
|
||||||
|
netty-threads="0"
|
||||||
|
codec-ref="myCodec"
|
||||||
|
use-linux-native-epoll="false"
|
||||||
|
redisson-reference-enabled="true"
|
||||||
|
codec-provider-ref="myCodecProvider"
|
||||||
|
resolver-provider-ref="myResolverProvider"
|
||||||
|
executor-ref="myExecutor"
|
||||||
|
event-loop-group-ref="myEventLoopGroup"
|
||||||
|
>
|
||||||
|
<!--
|
||||||
|
You can't have both name attribute and qualifier element at
|
||||||
|
the same time.
|
||||||
|
|
||||||
|
Both id attribute and name attribute can be used as qualifier
|
||||||
|
candidates.
|
||||||
|
-->
|
||||||
|
<!--<qualifier value="redisson3"/>-->
|
||||||
|
<redisson:cluster-servers
|
||||||
|
idle-connection-timeout="10000"
|
||||||
|
ping-timeout="1000"
|
||||||
|
connect-timeout="10000"
|
||||||
|
timeout="3000"
|
||||||
|
retry-attempts="3"
|
||||||
|
retry-interval="1500"
|
||||||
|
reconnection-timeout="3000"
|
||||||
|
failed-attempts="3"
|
||||||
|
password="do_not_use_if_it_is_not_set"
|
||||||
|
subscriptions-per-connection="5"
|
||||||
|
client-name="none"
|
||||||
|
load-balancer-ref="myLoadBalancer"
|
||||||
|
subscription-connection-minimum-idle-size="1"
|
||||||
|
subscription-connection-pool-size="50"
|
||||||
|
slave-connection-minimum-idle-size="10"
|
||||||
|
slave-connection-pool-size="64"
|
||||||
|
master-connection-minimum-idle-size="10"
|
||||||
|
master-connection-pool-size="64"
|
||||||
|
read-mode="SLAVE"
|
||||||
|
subscription-mode="SLAVE"
|
||||||
|
scan-interval="1000"
|
||||||
|
>
|
||||||
|
<redisson:node-address value="127.0.0.1:6379" />
|
||||||
|
<redisson:node-address value="127.0.0.1:6380" />
|
||||||
|
<redisson:node-address value="127.0.0.1:6381" />
|
||||||
|
</redisson:cluster-servers>
|
||||||
|
</redisson:client>
|
||||||
|
</beans>
|
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xmlns:redisson="http://redisson.org/schema/redisson"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
|
||||||
|
http://redisson.org/schema/redisson classpath:org/redisson/spring/support/redisson-1.0.xsd
|
||||||
|
">
|
||||||
|
<bean id="myCodec" class="org.redisson.codec.MsgPackJacksonCodec"/>
|
||||||
|
<bean id="myCodecProvider" class="org.redisson.codec.DefaultCodecProvider"/>
|
||||||
|
<bean id="myResolverProvider" class="org.redisson.liveobject.provider.DefaultResolverProvider"/>
|
||||||
|
<bean id="myExecutor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||||
|
<property name="staticMethod" value="java.util.concurrent.Executors.newFixedThreadPool"/>
|
||||||
|
<property name="arguments" value="8"/>
|
||||||
|
</bean>
|
||||||
|
<bean id="myEventLoopGroup" class="io.netty.channel.nio.NioEventLoopGroup"/>
|
||||||
|
<bean id="myLoadBalancer" class="org.redisson.connection.balancer.RoundRobinLoadBalancer"/>
|
||||||
|
|
||||||
|
<redisson:client
|
||||||
|
id="redisson"
|
||||||
|
name="redisson1,redisson2"
|
||||||
|
threads="0"
|
||||||
|
netty-threads="0"
|
||||||
|
codec-ref="myCodec"
|
||||||
|
use-linux-native-epoll="false"
|
||||||
|
redisson-reference-enabled="true"
|
||||||
|
codec-provider-ref="myCodecProvider"
|
||||||
|
resolver-provider-ref="myResolverProvider"
|
||||||
|
executor-ref="myExecutor"
|
||||||
|
event-loop-group-ref="myEventLoopGroup"
|
||||||
|
>
|
||||||
|
<!--
|
||||||
|
You can't have both name attribute and qualifier element at
|
||||||
|
the same time.
|
||||||
|
|
||||||
|
Both id attribute and name attribute can be used as qualifier
|
||||||
|
candidates.
|
||||||
|
-->
|
||||||
|
<!--<qualifier value="redisson3"/>-->
|
||||||
|
<redisson:master-slave-servers
|
||||||
|
idle-connection-timeout="10000"
|
||||||
|
ping-timeout="1000"
|
||||||
|
connect-timeout="10000"
|
||||||
|
timeout="3000"
|
||||||
|
retry-attempts="3"
|
||||||
|
retry-interval="1500"
|
||||||
|
reconnection-timeout="3000"
|
||||||
|
failed-attempts="3"
|
||||||
|
password="do_not_use_if_it_is_not_set"
|
||||||
|
subscriptions-per-connection="5"
|
||||||
|
client-name="none"
|
||||||
|
load-balancer-ref="myLoadBalancer"
|
||||||
|
subscription-connection-minimum-idle-size="1"
|
||||||
|
subscription-connection-pool-size="50"
|
||||||
|
slave-connection-minimum-idle-size="10"
|
||||||
|
slave-connection-pool-size="64"
|
||||||
|
master-connection-minimum-idle-size="10"
|
||||||
|
master-connection-pool-size="64"
|
||||||
|
read-mode="SLAVE"
|
||||||
|
subscription-mode="SLAVE"
|
||||||
|
master-address="127.0.0.1:6379"
|
||||||
|
database="0"
|
||||||
|
>
|
||||||
|
<redisson:slave-address value="127.0.0.1:6380" />
|
||||||
|
<redisson:slave-address value="127.0.0.1:6381" />
|
||||||
|
</redisson:master-slave-servers>
|
||||||
|
</redisson:client>
|
||||||
|
</beans>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue