Use alternative UUID strategy in MessageHeaders
This change adds an alternative UUID generation strategy to use by default in MessageHeaders. Instead of using SecureRandom for each new UUID, SecureRandom is used only for the initial seed to be provided java.util.Random. Thereafter the same Random instance is used instead. This provides improved performance while id's are still random but less securely so.
This commit is contained in:
@@ -20,6 +20,8 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -28,6 +30,7 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -56,6 +59,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
* @author Arjen Poutsma
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
* @see org.springframework.messaging.support.MessageBuilder
|
||||
*/
|
||||
@@ -65,9 +69,10 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MessageHeaders.class);
|
||||
|
||||
|
||||
private static volatile IdGenerator idGenerator = null;
|
||||
|
||||
private static volatile IdGenerator defaultIdGenerator = new AlternativeJdkIdGenerator();
|
||||
|
||||
/**
|
||||
* The key for the Message ID. This is an automatically generated UUID and
|
||||
* should never be explicitly set in the header map <b>except</b> in the
|
||||
@@ -92,13 +97,8 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
|
||||
public MessageHeaders(Map<String, Object> headers) {
|
||||
this.headers = (headers != null) ? new HashMap<String, Object>(headers) : new HashMap<String, Object>();
|
||||
if (MessageHeaders.idGenerator == null){
|
||||
this.headers.put(ID, UUID.randomUUID());
|
||||
}
|
||||
else {
|
||||
this.headers.put(ID, MessageHeaders.idGenerator.generateId());
|
||||
}
|
||||
|
||||
IdGenerator generatorToUse = (idGenerator != null) ? idGenerator : defaultIdGenerator;
|
||||
this.headers.put(ID, generatorToUse.generateId());
|
||||
this.headers.put(TIMESTAMP, new Long(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
@@ -247,4 +247,37 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
public static interface IdGenerator {
|
||||
UUID generateId();
|
||||
}
|
||||
|
||||
/**
|
||||
* A variation of {@link UUID#randomUUID()} that uses {@link SecureRandom} only for
|
||||
* the initial seed and {@link Random} thereafter, which provides better performance
|
||||
* in exchange for less securely random id's.
|
||||
*/
|
||||
public static class AlternativeJdkIdGenerator implements IdGenerator {
|
||||
|
||||
private final Random random;
|
||||
|
||||
public AlternativeJdkIdGenerator() {
|
||||
byte[] seed = new SecureRandom().generateSeed(8);
|
||||
this.random = new Random(new BigInteger(seed).longValue());
|
||||
}
|
||||
|
||||
public UUID generateId() {
|
||||
|
||||
byte[] randomBytes = new byte[16];
|
||||
this.random.nextBytes(randomBytes);
|
||||
|
||||
long mostSigBits = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
mostSigBits = (mostSigBits << 8) | (randomBytes[i] & 0xff);
|
||||
}
|
||||
long leastSigBits = 0;
|
||||
for (int i = 8; i < 16; i++) {
|
||||
leastSigBits = (leastSigBits << 8) | (randomBytes[i] & 0xff);
|
||||
}
|
||||
|
||||
return new UUID(mostSigBits, leastSigBits);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user