1 16 17 package org.springframework.aop.framework; 18 19 import java.io.Serializable ; 20 import java.lang.reflect.InvocationHandler ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Proxy ; 23 import java.util.List ; 24 25 import org.aopalliance.intercept.MethodInvocation; 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 29 import org.springframework.aop.TargetSource; 30 import org.springframework.aop.support.AopUtils; 31 import org.springframework.util.Assert; 32 import org.springframework.util.ClassUtils; 33 34 59 final class JdkDynamicAopProxy implements AopProxy, InvocationHandler , Serializable { 60 61 62 private static final long serialVersionUID = 5531744639992436476L; 63 64 65 73 74 75 private static Log logger = LogFactory.getLog(JdkDynamicAopProxy.class); 76 77 78 private final AdvisedSupport advised; 79 80 83 private boolean equalsDefined; 84 85 88 private boolean hashCodeDefined; 89 90 91 97 public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { 98 Assert.notNull(config, "AdvisedSupport must not be null"); 99 if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { 100 throw new AopConfigException("No advisors and no TargetSource specified"); 101 } 102 this.advised = config; 103 } 104 105 106 public Object getProxy() { 107 return getProxy(ClassUtils.getDefaultClassLoader()); 108 } 109 110 public Object getProxy(ClassLoader classLoader) { 111 if (logger.isDebugEnabled()) { 112 logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); 113 } 114 Class [] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); 115 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); 116 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 117 } 118 119 124 private void findDefinedEqualsAndHashCodeMethods(Class [] proxiedInterfaces) { 125 for (int i = 0; i < proxiedInterfaces.length; i++) { 126 Class proxiedInterface = proxiedInterfaces[i]; 127 Method [] methods = proxiedInterface.getDeclaredMethods(); 128 for (int j = 0; j < methods.length; j++) { 129 Method method = methods[j]; 130 if (AopUtils.isEqualsMethod(method)) { 131 this.equalsDefined = true; 132 } 133 if (AopUtils.isHashCodeMethod(method)) { 134 this.hashCodeDefined = true; 135 } 136 if (this.equalsDefined && this.hashCodeDefined) { 137 return; 138 } 139 } 140 } 141 } 142 143 144 149 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 150 MethodInvocation invocation = null; 151 Object oldProxy = null; 152 boolean setProxyContext = false; 153 154 TargetSource targetSource = this.advised.targetSource; 155 Class targetClass = null; 156 Object target = null; 157 158 try { 159 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { 160 return (equals(args[0]) ? Boolean.TRUE : Boolean.FALSE); 162 } 163 if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 164 return new Integer (hashCode()); 166 } 167 if (!this.advised.opaque && method.getDeclaringClass().isInterface() && 168 method.getDeclaringClass().isAssignableFrom(Advised.class)) { 169 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 171 } 172 173 Object retVal = null; 174 175 if (this.advised.exposeProxy) { 176 oldProxy = AopContext.setCurrentProxy(proxy); 178 setProxyContext = true; 179 } 180 181 target = targetSource.getTarget(); 184 if (target != null) { 185 targetClass = target.getClass(); 186 } 187 188 List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 190 191 if (chain.isEmpty()) { 194 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); 198 } 199 else { 200 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 202 retVal = invocation.proceed(); 204 } 205 206 if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) { 208 retVal = proxy; 212 } 213 return retVal; 214 } 215 finally { 216 if (target != null && !targetSource.isStatic()) { 217 targetSource.releaseTarget(target); 219 } 220 if (setProxyContext) { 221 AopContext.setCurrentProxy(oldProxy); 223 } 224 } 225 } 226 227 228 233 public boolean equals(Object other) { 234 if (other == this) { 235 return true; 236 } 237 if (other == null) { 238 return false; 239 } 240 241 JdkDynamicAopProxy otherProxy = null; 242 if (other instanceof JdkDynamicAopProxy) { 243 otherProxy = (JdkDynamicAopProxy) other; 244 } 245 else if (Proxy.isProxyClass(other.getClass())) { 246 InvocationHandler ih = Proxy.getInvocationHandler(other); 247 if (!(ih instanceof JdkDynamicAopProxy)) { 248 return false; 249 } 250 otherProxy = (JdkDynamicAopProxy) ih; 251 } 252 else { 253 return false; 255 } 256 257 return AopProxyUtils.equalsInProxy(this.advised, otherProxy.advised); 259 } 260 261 264 public int hashCode() { 265 return JdkDynamicAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode(); 266 } 267 268 } 269 | Popular Tags |