- 浏览: 133395 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (52)
- JPA (3)
- JSF (1)
- DesignPattern (0)
- Axis2 (2)
- Ibatis (2)
- Spring (4)
- Cache (2)
- log (1)
- Java (2)
- WebService (7)
- 系统集成 (1)
- PDF Generate (2)
- NoSQL (3)
- IOS (1)
- ISO Apple (1)
- 杂谈 (2)
- 内存泄露常用工具分析 (2)
- webshpere 拓扑结构 (2)
- Hadoop (3)
- FreeMarker (1)
- Security Related (3)
- BackBone (1)
- BackBone Web前端 MVC (1)
- teste (1)
- 架构分解 原则 (1)
- 架构 (2)
- REST API (1)
最新评论
-
OMG-SOCOOL:
不用单独加载指定的文件private static Confi ...
动态加载 bean 到Spring Context -
springdata_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
Spring MVC and FreeMarker Sample -
elicer:
zhongrf 写道请问为何用backbone?对银行系统合适 ...
BackBone介绍及使用 -
zhongrf:
请问为何用backbone?对银行系统合适么?
BackBone介绍及使用 -
heilinshuguang:
dear 动态加载bean已经了解。我现在有这样一个需 ...
动态加载 bean 到Spring Context
AOP的cache 大家都很熟悉,关于cachekey的生成方式有多种,最简单的是className+methodName+parameters ,这种方法的弊端太多,如果parameter是一个复合对像,那么在拼key时就比较麻烦。
我在以前的一片文章中讲过用annotation来标注复合对象中需要作为cache的子对象,能解决复合对象generate cachekey的问题,但这是一种侵入式的,需要加入额外的代码,真正的AOP cache应该式非侵入式的,就是cache的生效不需要其它代码有任何额外的工作。做function的程序员不需要关心cache的任何东西,cache对他们来说是透明的。
所以这里我想到了一种用HashCode来作为AOP cache的实现。这样不管参数的类型是什么,对于我generate cachekey 都没有影响。
具体实现类:
Key generate Interface
CacheGenerate 实现类
我在以前的一片文章中讲过用annotation来标注复合对象中需要作为cache的子对象,能解决复合对象generate cachekey的问题,但这是一种侵入式的,需要加入额外的代码,真正的AOP cache应该式非侵入式的,就是cache的生效不需要其它代码有任何额外的工作。做function的程序员不需要关心cache的任何东西,cache对他们来说是透明的。
所以这里我想到了一种用HashCode来作为AOP cache的实现。这样不管参数的类型是什么,对于我generate cachekey 都没有影响。
具体实现类:
Key generate Interface
import java.io.Serializable; import org.aopalliance.intercept.MethodInvocation; /** * <p> * Generates a unique key based on the description of an invocation to an * intercepted method. * </p> * * @author Elicer Zheng */ public interface CacheKeyGenerator { /** * Generates the key for a cache entry. * * @param methodInvocation * the description of an invocation to the intercepted method. * @return the created key. */ Serializable generateKey(MethodInvocation methodInvocation); }
CacheGenerate 实现类
import java.io.Serializable; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInvocation; /** * <p> * Generates the key for a cache entry using the hashCode of the intercepted * method and its arguments. * </p> * * @author Elicer Zheng */ public class HashCodeCacheKeyGenerator implements CacheKeyGenerator { /** * Flag that indicates if this generator should generate the hash code of the * arguments passed to the method to apply caching to. If <code>false</code>, * this generator uses the default hash code of the arguments. */ private boolean generateArgumentHashCode; /** * Construct a <code>HashCodeCacheKeyGenerator</code>. */ public HashCodeCacheKeyGenerator() { super(); } /** * Construct a <code>HashCodeCacheKeyGenerator</code>. * * @param generateArgumentHashCode * the new value for the flag that indicates if this generator should * generate the hash code of the arguments passed to the method to * apply caching to. If <code>false</code>, this generator uses * the default hash code of the arguments. */ public HashCodeCacheKeyGenerator(boolean generateArgumentHashCode) { this(); setGenerateArgumentHashCode(generateArgumentHashCode); } /** * @see CacheKeyGenerator#generateKey(MethodInvocation) */ public final Serializable generateKey(MethodInvocation methodInvocation) { HashCodeCalculator hashCodeCalculator = new HashCodeCalculator(); Method method = methodInvocation.getMethod(); hashCodeCalculator.append(System.identityHashCode(method)); Object[] methodArguments = methodInvocation.getArguments(); if (methodArguments != null) { int methodArgumentCount = methodArguments.length; for (int i = 0; i < methodArgumentCount; i++) { Object methodArgument = methodArguments[i]; int hash = 0; if (generateArgumentHashCode) { hash = ReflectionsUtility.reflectionHashCode(methodArgument); } else { hash = ObjectsUtility.nullSafeHashCode(methodArgument); } hashCodeCalculator.append(hash); } } long checkSum = hashCodeCalculator.getCheckSum(); int hashCode = hashCodeCalculator.getHashCode(); Serializable cacheKey = new HashCodeCacheKey(checkSum, hashCode); return cacheKey; } /** * Sets the flag that indicates if this generator should generate the hash * code of the arguments passed to the method to apply caching to. If * <code>false</code>, this generator uses the default hash code of the * arguments. * * @param newGenerateArgumentHashCode * the new value of the flag */ public final void setGenerateArgumentHashCode( boolean newGenerateArgumentHashCode) { generateArgumentHashCode = newGenerateArgumentHashCode; } }
import java.io.Serializable; /** * <p> * Cache key which value is based on a pre-calculated hash code. * </p> * * @author Elicer Zheng */ public final class HashCodeCacheKey implements Serializable { private static final long serialVersionUID = 3904677167731454262L; /** * Number that helps keep the uniqueness of this key. */ private long checkSum; /** * Pre-calculated hash code. */ private int hashCode; /** * Construct a <code>HashCodeCacheKey</code>. */ public HashCodeCacheKey() { super(); } /** * Construct a <code>HashCodeCacheKey</code>. * * @param newCheckSum * the number that helps keep the uniqueness of this key * @param newHashCode * the pre-calculated hash code */ public HashCodeCacheKey(long newCheckSum, int newHashCode) { this(); setCheckSum(newCheckSum); setHashCode(newHashCode); } /** * @see Object#equals(Object) */ public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof HashCodeCacheKey)) return false; HashCodeCacheKey other = (HashCodeCacheKey) obj; if (checkSum != other.checkSum) return false; if (hashCode != other.hashCode) return false; return true; } /** * @return the number that helps keep the uniqueness of this key */ public long getCheckSum() { return checkSum; } /** * @return the pre-calculated hash code */ public int getHashCode() { return hashCode; } /** * @see Object#hashCode() */ public int hashCode() { return getHashCode(); } /** * Sets the number that helps keep the uniqueness of this key. * * @param newCheckSum * the new number */ public void setCheckSum(long newCheckSum) { checkSum = newCheckSum; } /** * Sets the pre-calculated hash code. * * @param newHashCode * the new hash code */ public void setHashCode(int newHashCode) { hashCode = newHashCode; } /** * @see Object#toString() */ public String toString() { return getHashCode() + "|" + getCheckSum(); } }
/** * *This class is a HashCode Calculator * * @author Elicer Zheng */ public final class HashCodeCalculator { private static final int INITIAL_HASH = 17; private static final int MULTIPLIER = 37; private long checkSum; /** * Counts the number of times <code>{@link #append(int)}</code> is executed. * It is also used to build <code>{@link #checkSum}</code> and * <code>{@link #hashCode}</code>. */ private int count; /** * Hash code to build; */ private int hashCode; /** * Constructor. */ public HashCodeCalculator() { super(); hashCode = INITIAL_HASH; } /** * Recalculates <code>{@link #checkSum}</code> and * <code>{@link #hashCode}</code> using the specified value. * * @param value * the specified value. */ public void append(int value) { count++; int valueToAppend = count * value; hashCode = MULTIPLIER * hashCode + (valueToAppend ^ (valueToAppend >>> 16)); checkSum += valueToAppend; } /** * @return the number that ensures that the combination hashCode/checSum is * unique */ public long getCheckSum() { return checkSum; } /** * @return the calculated hash code */ public int getHashCode() { return hashCode; } }
import java.util.HashSet; import java.util.Set; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** * <p> * Miscellaneous object utility methods. * </p> * * @author Elicer Zheng */ public abstract class ObjectsUtility { private static final String ARRAY_ELEMENT_SEPARATOR = ", "; private static final String ARRAY_END = "}"; private static final String ARRAY_START = "{"; private static final String EMPTY_ARRAY = "{}"; private static final int INITIAL_HASH = 7; private static final int MULTIPLIER = 31; private static final String NULL_ARRAY = "null"; private static final Set primitivesAndWrappers; static { primitivesAndWrappers = new HashSet(); primitivesAndWrappers.add(boolean.class); primitivesAndWrappers.add(Boolean.class); primitivesAndWrappers.add(byte.class); primitivesAndWrappers.add(Byte.class); primitivesAndWrappers.add(char.class); primitivesAndWrappers.add(Character.class); primitivesAndWrappers.add(double.class); primitivesAndWrappers.add(Double.class); primitivesAndWrappers.add(float.class); primitivesAndWrappers.add(Float.class); primitivesAndWrappers.add(int.class); primitivesAndWrappers.add(Integer.class); primitivesAndWrappers.add(long.class); primitivesAndWrappers.add(Long.class); primitivesAndWrappers.add(short.class); primitivesAndWrappers.add(Short.class); } /** * Returns the same value as <code>{@link Boolean#hashCode()}</code>. * * @param bool * the given <code>boolean</code>. * @return the hash code for the given <code>boolean</code>. * @see Boolean#hashCode() */ public static int hashCode(boolean bool) { return bool ? 1231 : 1237; } /** * Returns the same value as <code>{@link Double#hashCode()}</code>. * * @param dbl * the given <code>double</code>. * @return the hash code for the given <code>double</code>. * @see Double#hashCode() */ public static int hashCode(double dbl) { long bits = Double.doubleToLongBits(dbl); return hashCode(bits); } /** * Returns the same value as <code>{@link Float#hashCode()}</code>. * * @param flt * the given <code>float</code>. * @return the hash code for the given <code>float</code>. * @see Float#hashCode() */ public static int hashCode(float flt) { return Float.floatToIntBits(flt); } /** * Returns the same value as <code>{@link Long#hashCode()}</code>. * * @param lng * the given <code>long</code>. * @return the hash code for the given <code>long</code>. * @see Long#hashCode() */ public static int hashCode(long lng) { return (int) (lng ^ (lng >>> 32)); } /** * <p> * Returns a <code>StringBuffer</code> containing: * <ol> * <li>the class name of the given object</li> * <li>the character '@'</li> * <li>the hex string for the object's identity hash code</li> * </ol> * </p> * <p> * This method will return an empty <code>StringBuffer</code> if the given * object is <code>null</code>. * </p> * * @param obj * the given object. * @return a <code>StringBuffer</code> containing identity information of * the given object. */ public static StringBuffer identityToString(Object obj) { StringBuffer buffer = new StringBuffer(); if (obj != null) { buffer.append(obj.getClass().getName()); buffer.append("@"); buffer.append(ObjectUtils.getIdentityHexString(obj)); } return buffer; } /** * Returns <code>true</code> if the given object is an array of primitives. * * @param array * the given object to check. * @return <code>true</code> if the given object is an array of primitives. */ public static boolean isArrayOfPrimitives(Object array) { boolean primitiveArray = false; if (array != null) { Class clazz = array.getClass(); primitiveArray = clazz.isArray() && clazz.getComponentType().isPrimitive(); } return primitiveArray; } /** * Returns <code>true</code> if the given class is any of the following: * <ul> * <li><code>boolean</code></li> * <li>Boolean</li> * <li><code>byte</code></li> * <li>Byte</li> * <li><code>char</code></li> * <li>Character</li> * <li><code>double</code></li> * <li>Double</li> * <li><code>float</code></li> * <li>Float</li> * <li><code>int</code></li> * <li>Integer</li> * <li><code>long</code></li> * <li>Long</li> * <li><code>short</code></li> * <li>Short</li> * </ul> * * @param clazz * the given class. * @return <code>true</code> if the given class represents a primitive or a * wrapper, <code>false</code> otherwise. */ public static boolean isPrimitiveOrWrapper(Class clazz) { return primitivesAndWrappers.contains(clazz); } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>boolean</code> arrays <code>a</code> and <code>b</code> * such that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * </p> * * @param array * the array whose hash value to compute. * @return a content-based hash code for <code>array</code>. * @see #hashCode(boolean) */ public static int nullSafeHashCode(boolean[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + hashCode(array[i]); } return hash; } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>byte</code> arrays <code>a</code> and <code>b</code> such * that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * </p> * * @param array * the array whose hash value to compute. * @return a content-based hash code for <code>array</code>. */ public static int nullSafeHashCode(byte[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + array[i]; } return hash; } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>char</code> arrays <code>a</code> and <code>b</code> such * that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * </p> * * @param array * the array whose hash value to compute. * @return a content-based hash code for <code>array</code>. */ public static int nullSafeHashCode(char[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + array[i]; } return hash; } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>double</code> arrays <code>a</code> and <code>b</code> such * that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * </p> * * @param array * the array whose hash value to compute. * @return a content-based hash code for <code>array</code>. * @see #hashCode(double) */ public static int nullSafeHashCode(double[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + hashCode(array[i]); } return hash; } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>float</code> arrays <code>a</code> and <code>b</code> such * that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * </p> * * @param array * the array whose hash value to compute. * @return a content-based hash code for <code>array</code>. * @see #hashCode(float) */ public static int nullSafeHashCode(float[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + hashCode(array[i]); } return hash; } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>int</code> arrays <code>a</code> and <code>b</code> such * that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * </p> * * @param array * the array whose hash value to compute. * @return a content-based hash code for <code>array</code>. */ public static int nullSafeHashCode(int[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + array[i]; } return hash; } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>long</code> arrays <code>a</code> and <code>b</code> such * that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * </p> * * @param array * the array whose hash value to compute. * @return a content-based hash code for <code>array</code>. * @see #hashCode(long) */ public static int nullSafeHashCode(long[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + hashCode(array[i]); } return hash; } /** * <p> * Returns the value of <code>{@link Object#hashCode()}</code>. If the * object is an array, this method will delegate to any of the * <code>nullSafeHashCode</code> methods for arrays in this class. * </p> * * <p> * If the object is <code>null</code>, this method returns 0. * </p> * * @param obj * the object whose hash value to compute. * @return the hash code of the given object. * @see #nullSafeHashCode(boolean[]) * @see #nullSafeHashCode(byte[]) * @see #nullSafeHashCode(char[]) * @see #nullSafeHashCode(double[]) * @see #nullSafeHashCode(float[]) * @see #nullSafeHashCode(int[]) * @see #nullSafeHashCode(long[]) * @see #nullSafeHashCode(Object[]) * @see #nullSafeHashCode(short[]) */ public static int nullSafeHashCode(Object obj) { if (obj == null) return 0; if (obj instanceof boolean[]) { return nullSafeHashCode((boolean[]) obj); } if (obj instanceof byte[]) { return nullSafeHashCode((byte[]) obj); } if (obj instanceof char[]) { return nullSafeHashCode((char[]) obj); } if (obj instanceof double[]) { return nullSafeHashCode((double[]) obj); } if (obj instanceof float[]) { return nullSafeHashCode((float[]) obj); } if (obj instanceof int[]) { return nullSafeHashCode((int[]) obj); } if (obj instanceof long[]) { return nullSafeHashCode((long[]) obj); } if (obj instanceof short[]) { return nullSafeHashCode((short[]) obj); } if (obj instanceof Object[]) { return nullSafeHashCode((Object[]) obj); } return obj.hashCode(); } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two arrays <code>a</code> and <code>b</code> such that * <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * <p> * The value returned by this method is equal to the value that would be * returned by <code>Arrays.asList(a).hashCode()</code>, unless * <code>array</code> is <code>null</code>, in which case <code>0</code> * is returned. * </p> * * @param array * the array whose content-based hash code to compute. * @return a content-based hash code for <code>array</code>. */ public static int nullSafeHashCode(Object[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + nullSafeHashCode(array[i]); } return hash; } /** * <p> * Returns a hash code based on the contents of the specified array. For any * two <code>short</code> arrays <code>a</code> and <code>b</code> such * that <code>Arrays.equals(a, b)</code>, it is also the case that * <code>Arrays.hashCode(a) == Arrays.hashCode(b)</code>. * </p> * * <p> * If <code>array</code> is <code>null</code>, this method returns 0. * * @param array * the array whose hash value to compute * @return a content-based hash code for <code>array</code> */ public static int nullSafeHashCode(short[] array) { if (array == null) return 0; int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + array[i]; } return hash; } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(boolean[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(array[i]); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(byte[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(array[i]); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(char[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append("'" + array[i] + "'"); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(double[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(array[i]); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(float[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(array[i]); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(int[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(array[i]); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(long[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(array[i]); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(Object[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(StringUtils.quoteIfString(array[i])); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(short[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(array[i]); } buffer.append(ARRAY_END); return buffer.toString(); } /** * Returns a string representation of the contents of the specified array. The * string representation consists of a list of the array's elements, enclosed * in curly braces (<code>"{}"</code>). Adjacent elements are separated by * the characters <code>", "</code> (a comma followed by a space). Returns * <code>"null"</code> if <code>array</code> is <code>null</code>. * * @param array * the array whose string representation to return. * @return a string representation of <code>array</code>. */ public static String nullSafeToString(String[] array) { if (array == null) return NULL_ARRAY; int length = array.length; if (length == 0) return EMPTY_ARRAY; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < length; i++) { if (i == 0) buffer.append(ARRAY_START); else buffer.append(ARRAY_ELEMENT_SEPARATOR); buffer.append(StringUtils.quote(array[i])); } buffer.append(ARRAY_END); return buffer.toString(); } }
import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; import java.util.Map; import org.springframework.util.ReflectionUtils; /** * <p> * Reflection-related utility methods,used to build the hash code for the input parameter. * </p> * * * @author Elicer Zheng */ public abstract class ReflectionsUtility { private static final int INITIAL_HASH = 7; private static final int MULTIPLIER = 31; /** * <p> * This method uses reflection to build a valid hash code. * </p> * * <p> * It uses <code>AccessibleObject.setAccessible</code> to gain access to * private fields. This means that it will throw a security exception if run * under a security manager, if the permissions are not set up correctly. It * is also not as efficient as testing explicitly. * </p> * * <p> * Transient members will not be used, as they are likely derived fields, * and not part of the value of the <code>Object</code>. * </p> * * <p> * Static fields will not be tested. Superclass fields will be included. * </p> * * @param obj * the object to create a <code>hashCode</code> for * @return the generated hash code, or zero if the given object is * <code>null</code> */ public static int reflectionHashCode(Object obj) { if (obj == null) return 0; Class targetClass = obj.getClass(); if (ObjectsUtility.isArrayOfPrimitives(obj) || ObjectsUtility.isPrimitiveOrWrapper(targetClass)) { return ObjectsUtility.nullSafeHashCode(obj); } if (targetClass.isArray()) { return reflectionHashCode((Object[]) obj); } if (obj instanceof Collection) { return reflectionHashCode((Collection) obj); } if (obj instanceof Map) { return reflectionHashCode((Map) obj); } // determine whether the object's class declares hashCode() or has a // superClass other than java.lang.Object that declares hashCode() Class clazz = (obj instanceof Class)? (Class) obj : obj.getClass(); Method hashCodeMethod = ReflectionUtils.findMethod(clazz, "hashCode", new Class[0]); if (hashCodeMethod != null) { return obj.hashCode(); } // could not find a hashCode other than the one declared by java.lang.Object int hash = INITIAL_HASH; try { while (targetClass != null) { Field[] fields = targetClass.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; int modifiers = field.getModifiers(); if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) { hash = MULTIPLIER * hash + reflectionHashCode(field.get(obj)); } } targetClass = targetClass.getSuperclass(); } } catch (IllegalAccessException exception) { // ///CLOVER:OFF ReflectionUtils.handleReflectionException(exception); // ///CLOVER:ON } return hash; } private static int reflectionHashCode(Collection collection) { int hash = INITIAL_HASH; for (Iterator i = collection.iterator(); i.hasNext();) { hash = MULTIPLIER * hash + reflectionHashCode(i.next()); } return hash; } private static int reflectionHashCode(Map map) { int hash = INITIAL_HASH; for (Iterator i = map.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); hash = MULTIPLIER * hash + reflectionHashCode(entry); } return hash; } private static int reflectionHashCode(Map.Entry entry) { int hash = INITIAL_HASH; hash = MULTIPLIER * hash + reflectionHashCode(entry.getKey()); hash = MULTIPLIER * hash + reflectionHashCode(entry.getValue()); return hash; } private static int reflectionHashCode(Object[] array) { int hash = INITIAL_HASH; int arraySize = array.length; for (int i = 0; i < arraySize; i++) { hash = MULTIPLIER * hash + reflectionHashCode(array[i]); } return hash; } }
相关推荐
在IT行业中,Spring AOP(面向切面编程)和Ehcache是两个非常重要的概念,它们经常被结合在一起用于实现高效的应用程序缓存系统。在这个"AOP Cache源代码"项目中,我们可以看到如何利用这两者来提升应用性能。下面将...
本实例将介绍如何利用Spring AOP来实现自定义缓存功能。 首先,理解Spring AOP的基本概念。AOP是一种编程范式,它允许我们在不修改代码的情况下,为程序添加额外的功能,如日志记录、事务管理、安全检查等。在...
2. Unity AOP:Unity提供了对AOP的支持,可以通过拦截器(Interceptor)实现。拦截器是实现AOP的核心,它在方法调用前后执行自定义逻辑。 3. 创建拦截器:通过继承`IInterceptor`接口或使用`Unity.Interception`库...
**AOP思想与Java实现** 面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它旨在解决传统面向对象编程中的横切关注点,如日志、事务管理、性能监控等,这些关注点往往分散在程序的各个角落,...
本篇文章将深入探讨如何通过Spring的注解方式实现AOP的细节。 首先,我们需要了解AOP的基本概念。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或责任。切点(Pointcut)定义了哪些方法会被通知(Advice...
基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop
**Spring AOP 学习笔记及实现Demo** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架中的一个重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP的主要目的...
Spring AOP 实现原理详解之 AOP 切面的实现 Spring AOP 是基于 IOC 的 Bean 加载来实现的,本文主要介绍 Spring AOP 原理解析的切面实现过程。AOP 切面的实现是将切面类的所有切面方法根据使用的注解生成对应 ...
动态代理是实现AOP的一种常用技术,它允许在运行时创建代理对象,拦截对真实对象的调用,并在调用前后添加额外的行为。 在Java开发中,反射机制是实现动态代理的关键技术之一。反射提供了在运行时访问和操作类的...
本例提供了一个简单的AOP拦截器实现,我们可以从这个基础出发,深入理解和探讨AOP的核心概念、工作原理以及其在实际开发中的应用。 首先,AOP的主要目标是解决程序中的横切关注点,如日志记录、事务管理、性能监控...
在本项目中,我们将探讨如何通过配置文件实现Spring AOP,包括前置通知、后置通知以及拦截器的运用。 首先,我们需要理解Spring AOP的核心概念。切面(Aspect)是关注点的模块化,这些关注点定义了跨越多个对象的...
在C#中,实现AOP的方法多种多样,以下将详细介绍几种常见的实现方式。 1. **静态织入**: 静态织入是在编译时完成的,它通过编译器或者编译插件(如PostSharp)在目标类的代码中插入拦截逻辑。这种方式的优点是...
在.NET平台上实现AOP,我们可以借助于不同的库和技术,如PostSharp、Unity、Autofac等。下面我们将深入探讨.NET平台AOP的实现方法和应用。 首先,我们需要理解AOP的基本概念。AOP的核心是切面(Aspect),它封装了...
本篇文章将详细讲解Spring AOP的四种常见实现方式,以帮助开发者更好地理解和运用这一功能。 一、基于接口的代理(Interface-Based Proxy) 这是Spring AOP的默认实现方式,适用于目标对象实现了接口的情况。Spring...
在本实战项目"AOP-cache"中,我们将深入探讨如何利用面向切面编程(AOP)和Ehcache技术来实现高效的数据缓存处理。面向切面编程是一种编程范式,它允许开发者将关注点分离,比如日志、事务管理、性能监控等,从主...
动态代理则是Spring AOP实现的核心技术之一,它允许我们在运行时创建具有额外行为的对象。下面将详细阐述Spring AOP的配置以及动态代理的实现。 一、Spring AOP基础知识 1. **什么是AOP**:AOP是一种编程范式,...
一个简单的采用自定义注解结合SpringAop实现方法执行的权限管理,这个demo中并没有涉及到与数据库的交互和业务代码,用户权限在登陆时采用简单的手动初始化。该demo用的jdk1.7编译,Spring4.0版本,只想通过这个demo...
在这个场景中,我们将使用Spring AOP来实现一个日志记录的功能,以追踪系统中各个方法的调用情况,包括访问时间以及传递的参数。下面将详细阐述如何实现这一目标。 首先,我们需要了解AOP的基本概念。AOP的核心是切...
本示例提供了一种通过注解和配置文件两种方式实现Spring AOP的方法。 首先,我们来详细讲解通过注解实现Spring AOP。在Spring中,我们可以使用`@Aspect`注解来定义一个切面,这个切面包含了多个通知(advice),即...
本文首先将传统基于OOP策略模式的局限性进行分析说明,提出基本的策略模式以及“链式”策略模式基于AOP的具体实现,解决传统策略模式可能出现的代码分散、代码混乱问题;接着进行复杂度方面的实验对比分析;最后分析...