1 16 17 package org.springframework.aop.framework; 18 19 import java.io.Serializable ; 20 import java.lang.reflect.Method ; 21 import java.lang.reflect.Modifier ; 22 import java.lang.reflect.UndeclaredThrowableException ; 23 import java.util.HashMap ; 24 import java.util.HashSet ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.Set ; 28 29 import net.sf.cglib.core.CodeGenerationException; 30 import net.sf.cglib.proxy.Callback; 31 import net.sf.cglib.proxy.CallbackFilter; 32 import net.sf.cglib.proxy.Dispatcher; 33 import net.sf.cglib.proxy.Enhancer; 34 import net.sf.cglib.proxy.Factory; 35 import net.sf.cglib.proxy.MethodInterceptor; 36 import net.sf.cglib.proxy.MethodProxy; 37 import net.sf.cglib.proxy.NoOp; 38 import net.sf.cglib.transform.impl.UndeclaredThrowableStrategy; 39 import org.aopalliance.aop.Advice; 40 import org.aopalliance.intercept.MethodInvocation; 41 import org.apache.commons.logging.Log; 42 import org.apache.commons.logging.LogFactory; 43 44 import org.springframework.aop.Advisor; 45 import org.springframework.aop.PointcutAdvisor; 46 import org.springframework.aop.support.AopUtils; 47 import org.springframework.util.Assert; 48 import org.springframework.util.ObjectUtils; 49 50 74 final class Cglib2AopProxy implements AopProxy, Serializable { 75 76 private static final int AOP_PROXY = 0; 78 private static final int INVOKE_TARGET = 1; 79 private static final int NO_OVERRIDE = 2; 80 private static final int DISPATCH_TARGET = 3; 81 private static final int DISPATCH_ADVISED = 4; 82 private static final int INVOKE_EQUALS = 5; 83 private static final int INVOKE_HASHCODE = 6; 84 85 86 87 protected final static Log logger = LogFactory.getLog(Cglib2AopProxy.class); 88 89 90 private static final Set validatedClasses = new HashSet (); 91 92 93 94 protected final AdvisedSupport advised; 95 96 private Object [] constructorArgs; 97 98 private Class [] constructorArgTypes; 99 100 101 private final transient AdvisedDispatcher advisedDispatcher; 102 103 private transient Map fixedInterceptorMap; 104 105 private transient int fixedInterceptorOffset; 106 107 108 114 public Cglib2AopProxy(AdvisedSupport config) throws AopConfigException { 115 Assert.notNull(config, "AdvisedSupport must not be null"); 116 if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { 117 throw new AopConfigException("No advisors and no TargetSource specified"); 118 } 119 this.advised = config; 120 this.advisedDispatcher = new AdvisedDispatcher(this.advised); 121 } 122 123 128 public void setConstructorArguments(Object [] constructorArgs, Class [] constructorArgTypes) { 129 if (constructorArgs == null || constructorArgTypes == null) { 130 throw new IllegalArgumentException ("Both 'constructorArgs' and 'constructorArgTypes' need to be specified"); 131 } 132 if (constructorArgs.length != constructorArgTypes.length) { 133 throw new IllegalArgumentException ("Number of 'constructorArgs' (" + constructorArgs.length + 134 ") must match number of 'constructorArgTypes' (" + constructorArgTypes.length + ")"); 135 } 136 this.constructorArgs = constructorArgs; 137 this.constructorArgTypes = constructorArgTypes; 138 } 139 140 141 public Object getProxy() { 142 return getProxy(null); 143 } 144 145 public Object getProxy(ClassLoader classLoader) { 146 if (logger.isDebugEnabled()) { 147 logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource()); 148 } 149 150 Enhancer enhancer = createEnhancer(); 151 try { 152 if (classLoader != null) { 154 enhancer.setClassLoader(classLoader); 155 } 156 157 Class rootClass = this.advised.getTargetClass(); 158 Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); 159 Class proxySuperClass = rootClass; 160 161 if (AopUtils.isCglibProxyClass(rootClass)) { 162 proxySuperClass = rootClass.getSuperclass(); 163 Class [] additionalInterfaces = rootClass.getInterfaces(); 164 for (int i = 0; i < additionalInterfaces.length; i++) { 165 Class additionalInterface = additionalInterfaces[i]; 166 this.advised.addInterface(additionalInterface); 167 } 168 } 169 170 validateClassIfNecessary(proxySuperClass); 172 173 enhancer.setSuperclass(proxySuperClass); 174 enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException .class)); 175 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); 176 enhancer.setInterceptDuringConstruction(false); 177 178 Callback[] callbacks = getCallbacks(rootClass); 179 enhancer.setCallbacks(callbacks); 180 enhancer.setCallbackFilter( 181 new ProxyCallbackFilter(this.advised, this.fixedInterceptorMap, this.fixedInterceptorOffset)); 182 183 Class [] types = new Class [callbacks.length]; 184 for (int x = 0; x < types.length; x++) { 185 types[x] = callbacks[x].getClass(); 186 } 187 enhancer.setCallbackTypes(types); 188 189 Object proxy; 191 if (this.constructorArgs != null) { 192 proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs); 193 } 194 else { 195 proxy = enhancer.create(); 196 } 197 198 return proxy; 199 } 200 catch (CodeGenerationException ex) { 201 throw new AopConfigException("Couldn't generate CGLIB subclass of class [" + 202 this.advised.getTargetClass() + "]: " + 203 "Common causes of this problem include using a final class or a non-visible class", 204 ex); 205 } 206 catch (IllegalArgumentException ex) { 207 throw new AopConfigException("Couldn't generate CGLIB subclass of class [" + 208 this.advised.getTargetClass() + "]: " + 209 "Common causes of this problem include using a final class or a non-visible class", 210 ex); 211 } 212 catch (Exception ex) { 213 throw new AopConfigException("Unexpected AOP exception", ex); 215 } 216 } 217 218 222 protected Enhancer createEnhancer() { 223 return new Enhancer(); 224 } 225 226 230 private void validateClassIfNecessary(Class proxySuperClass) { 231 if (logger.isWarnEnabled()) { 232 synchronized (validatedClasses) { 233 if (!validatedClasses.contains(proxySuperClass)) { 234 doValidateClass(proxySuperClass); 235 validatedClasses.add(proxySuperClass); 236 } 237 } 238 } 239 } 240 241 245 private void doValidateClass(Class proxySuperClass) { 246 Method [] methods = proxySuperClass.getMethods(); 247 for (int i = 0; i < methods.length; i++) { 248 Method method = methods[i]; 249 if (!Object .class.equals(method.getDeclaringClass()) && Modifier.isFinal(method.getModifiers())) { 250 logger.warn("Unable to proxy method [" + method + "] because it is final: " + 251 "All calls to this method via a proxy will be routed directly to the proxy."); 252 } 253 } 254 } 255 256 private Callback[] getCallbacks(Class rootClass) throws Exception { 257 boolean exposeProxy = this.advised.isExposeProxy(); 259 boolean isFrozen = this.advised.isFrozen(); 260 boolean isStatic = this.advised.getTargetSource().isStatic(); 261 262 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); 264 265 Callback targetInterceptor = null; 268 269 if (exposeProxy) { 270 targetInterceptor = isStatic ? 271 (Callback) new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : 272 (Callback) new DynamicUnadvisedExposedInterceptor(this.advised); 273 } 274 else { 275 targetInterceptor = isStatic ? 276 (Callback) new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : 277 (Callback) new DynamicUnadvisedInterceptor(this.advised); 278 } 279 280 Callback targetDispatcher = isStatic ? 283 (Callback) new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp(); 284 285 Callback[] mainCallbacks = new Callback[]{ 286 aopInterceptor, targetInterceptor, new SerializableNoOp(), targetDispatcher, this.advisedDispatcher, 290 new EqualsInterceptor(this.advised), 291 new HashCodeInterceptor(this.advised) 292 }; 293 294 Callback[] callbacks; 295 296 if (isStatic && isFrozen) { 300 Method [] methods = rootClass.getMethods(); 301 Callback[] fixedCallbacks = new Callback[methods.length]; 302 this.fixedInterceptorMap = new HashMap (methods.length); 303 304 for (int x = 0; x < methods.length; x++) { 307 List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); 308 fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( 309 chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); 310 this.fixedInterceptorMap.put(methods[x].toString(), new Integer (x)); 311 } 312 313 callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; 316 317 for (int x = 0; x < mainCallbacks.length; x++) { 318 callbacks[x] = mainCallbacks[x]; 319 } 320 321 for (int x = 0; x < fixedCallbacks.length; x++) { 322 callbacks[x + mainCallbacks.length] = fixedCallbacks[x]; 323 } 324 325 this.fixedInterceptorOffset = mainCallbacks.length; 326 } 327 else { 328 callbacks = mainCallbacks; 329 } 330 return callbacks; 331 } 332 333 336 private static Object massageReturnTypeIfNecessary(Object proxy, Object target, Object retVal) { 337 if (retVal != null && retVal == target) { 339 retVal = proxy; 343 } 344 return retVal; 345 } 346 347 348 public boolean equals(Object other) { 349 return (this == other || (other instanceof Cglib2AopProxy && 350 AopProxyUtils.equalsInProxy(this.advised, ((Cglib2AopProxy) other).advised))); 351 } 352 353 public int hashCode() { 354 return Cglib2AopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode(); 355 } 356 357 358 362 public static class SerializableNoOp implements NoOp, Serializable { 363 } 364 365 366 372 private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable { 373 374 private final Object target; 375 376 public StaticUnadvisedInterceptor(Object target) { 377 this.target = target; 378 } 379 380 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable { 381 Object retVal = methodProxy.invoke(this.target, args); 382 return massageReturnTypeIfNecessary(proxy, this.target, retVal); 383 } 384 } 385 386 387 391 private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable { 392 393 private final Object target; 394 395 public StaticUnadvisedExposedInterceptor(Object target) { 396 this.target = target; 397 } 398 399 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable { 400 Object oldProxy = null; 401 try { 402 oldProxy = AopContext.setCurrentProxy(proxy); 403 Object retVal = methodProxy.invoke(this.target, args); 404 return massageReturnTypeIfNecessary(proxy, this.target, retVal); 405 } 406 finally { 407 AopContext.setCurrentProxy(oldProxy); 408 } 409 } 410 } 411 412 413 418 private static class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable { 419 420 private final AdvisedSupport advised; 421 422 public DynamicUnadvisedInterceptor(AdvisedSupport advised) { 423 this.advised = advised; 424 } 425 426 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable { 427 Object target = this.advised.getTargetSource().getTarget(); 428 try { 429 Object retVal = methodProxy.invoke(target, args); 430 return massageReturnTypeIfNecessary(proxy, target, retVal); 431 } 432 finally { 433 this.advised.getTargetSource().releaseTarget(target); 434 } 435 } 436 } 437 438 439 442 private static class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable { 443 444 private final AdvisedSupport advised; 445 446 public DynamicUnadvisedExposedInterceptor(AdvisedSupport advised) { 447 this.advised = advised; 448 } 449 450 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable { 451 Object oldProxy = null; 452 Object target = this.advised.getTargetSource().getTarget(); 453 try { 454 oldProxy = AopContext.setCurrentProxy(proxy); 455 Object retVal = methodProxy.invoke(target, args); 456 return massageReturnTypeIfNecessary(proxy, target, retVal); 457 } 458 finally { 459 AopContext.setCurrentProxy(oldProxy); 460 this.advised.getTargetSource().releaseTarget(target); 461 } 462 } 463 } 464 465 466 471 private static class StaticDispatcher implements Dispatcher, Serializable { 472 473 private Object target; 474 475 public StaticDispatcher(Object target) { 476 this.target = target; 477 } 478 479 public Object loadObject() { 480 return this.target; 481 } 482 } 483 484 485 488 private static class AdvisedDispatcher implements Dispatcher, Serializable { 489 490 private final AdvisedSupport advised; 491 492 public AdvisedDispatcher(AdvisedSupport advised) { 493 this.advised = advised; 494 } 495 496 public Object loadObject() throws Exception { 497 return this.advised; 498 } 499 } 500 501 502 506 private static class EqualsInterceptor implements MethodInterceptor, Serializable { 507 508 private final AdvisedSupport advised; 509 510 public EqualsInterceptor(AdvisedSupport advised) { 511 this.advised = advised; 512 } 513 514 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) { 515 Object other = args[0]; 516 if (proxy == other) { 517 return Boolean.TRUE; 518 } 519 AdvisedSupport otherAdvised = null; 520 if (other instanceof Factory) { 521 Callback callback = ((Factory) other).getCallback(INVOKE_EQUALS); 522 if (!(callback instanceof EqualsInterceptor)) { 523 return Boolean.FALSE; 524 } 525 otherAdvised = ((EqualsInterceptor) callback).advised; 526 } 527 else { 528 return Boolean.FALSE; 529 } 530 return (AopProxyUtils.equalsInProxy(this.advised, otherAdvised) ? Boolean.TRUE : Boolean.FALSE); 531 } 532 } 533 534 535 539 private static class HashCodeInterceptor implements MethodInterceptor, Serializable { 540 541 private final AdvisedSupport advised; 542 543 public HashCodeInterceptor(AdvisedSupport advised) { 544 this.advised = advised; 545 } 546 547 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) { 548 return new Integer (Cglib2AopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode()); 549 } 550 } 551 552 553 556 private static class FixedChainStaticTargetInterceptor implements MethodInterceptor, Serializable { 557 558 private final List adviceChain; 559 560 private final Object target; 561 562 private final Class targetClass; 563 564 public FixedChainStaticTargetInterceptor(List adviceChain, Object target, Class targetClass) { 565 this.adviceChain = adviceChain; 566 this.target = target; 567 this.targetClass = targetClass; 568 } 569 570 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable { 571 Object retVal = null; 572 MethodInvocation invocation = new CglibMethodInvocation(proxy, this.target, method, args, 573 this.targetClass, this.adviceChain, methodProxy); 574 retVal = invocation.proceed(); 576 retVal = massageReturnTypeIfNecessary(proxy, this.target, retVal); 577 return retVal; 578 } 579 } 580 581 582 586 private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { 587 588 private AdvisedSupport advised; 589 590 public DynamicAdvisedInterceptor(AdvisedSupport advised) { 591 this.advised = advised; 592 } 593 594 public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable { 595 MethodInvocation invocation = null; 596 Object oldProxy = null; 597 boolean setProxyContext = false; 598 Class targetClass = null; 599 Object target = null; 600 try { 601 Object retVal = null; 602 if (this.advised.exposeProxy) { 603 oldProxy = AopContext.setCurrentProxy(proxy); 605 setProxyContext = true; 606 } 607 target = getTarget(); 610 if (target != null) { 611 targetClass = target.getClass(); 612 } 613 List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 614 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { 617 retVal = methodProxy.invoke(target, args); 622 } 623 else { 624 invocation = new CglibMethodInvocation(proxy, target, method, args, 626 targetClass, chain, methodProxy); 627 retVal = invocation.proceed(); 629 } 630 631 retVal = massageReturnTypeIfNecessary(proxy, target, retVal); 632 return retVal; 633 } 634 finally { 635 if (target != null) { 636 releaseTarget(target); 637 } 638 if (setProxyContext) { 639 AopContext.setCurrentProxy(oldProxy); 641 } 642 } 643 } 644 645 public boolean equals(Object other) { 646 return (this == other || 647 (other instanceof DynamicAdvisedInterceptor && 648 this.advised.equals(((DynamicAdvisedInterceptor) other).advised))); 649 } 650 651 654 public int hashCode() { 655 return this.advised.hashCode(); 656 } 657 658 protected Object getTarget() throws Exception { 659 return this.advised.getTargetSource().getTarget(); 660 } 661 662 protected void releaseTarget(Object target) throws Exception { 663 this.advised.getTargetSource().releaseTarget(target); 664 } 665 } 666 667 668 671 private static class CglibMethodInvocation extends ReflectiveMethodInvocation { 672 673 private final MethodProxy methodProxy; 674 675 private boolean protectedMethod; 676 677 public CglibMethodInvocation(Object proxy, Object target, Method method, Object [] arguments, 678 Class targetClass, List interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) { 679 super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers); 680 this.methodProxy = methodProxy; 681 this.protectedMethod = Modifier.isProtected(method.getModifiers()); 682 } 683 684 688 protected Object invokeJoinpoint() throws Throwable { 689 if (this.protectedMethod) { 690 return super.invokeJoinpoint(); 691 } 692 else { 693 return this.methodProxy.invoke(this.target, this.arguments); 694 } 695 } 696 } 697 698 699 702 private static class ProxyCallbackFilter implements CallbackFilter { 703 704 private final AdvisedSupport advised; 705 706 private final Map fixedInterceptorMap; 707 708 private final int fixedInterceptorOffset; 709 710 public ProxyCallbackFilter(AdvisedSupport advised, Map fixedInterceptorMap, int fixedInterceptorOffset) { 711 this.advised = advised; 712 this.fixedInterceptorMap = fixedInterceptorMap; 713 this.fixedInterceptorOffset = fixedInterceptorOffset; 714 } 715 716 752 public int accept(Method method) { 753 if (method.getDeclaringClass() == Object .class && method.getName().equals("finalize")) { 754 logger.debug("Found finalize() method - using NO_OVERRIDE"); 755 return NO_OVERRIDE; 756 } 757 if (!this.advised.opaque && method.getDeclaringClass().isInterface() && 758 method.getDeclaringClass().isAssignableFrom(Advised.class)) { 759 if (logger.isDebugEnabled()) { 760 logger.debug("Method is declared on Advised interface: " + method); 761 } 762 return DISPATCH_ADVISED; 763 } 764 if (AopUtils.isEqualsMethod(method)) { 766 logger.debug("Found 'equals' method: " + method); 767 return INVOKE_EQUALS; 768 } 769 if (AopUtils.isHashCodeMethod(method)) { 771 logger.debug("Found 'hashCode' method: " + method); 772 return INVOKE_HASHCODE; 773 } 774 Class targetClass = this.advised.getTargetClass(); 775 List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 777 boolean haveAdvice = !chain.isEmpty(); 778 boolean exposeProxy = this.advised.isExposeProxy(); 779 boolean isStatic = this.advised.getTargetSource().isStatic(); 780 boolean isFrozen = this.advised.isFrozen(); 781 if (haveAdvice || !isFrozen) { 782 if (exposeProxy) { 784 if (logger.isDebugEnabled()) { 785 logger.debug("Must expose proxy on advised method: " + method); 786 } 787 return AOP_PROXY; 788 } 789 String key = method.toString(); 790 if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) { 793 if (logger.isDebugEnabled()) { 794 logger.debug("Method has advice and optimisations are enabled: " + method); 795 } 796 int index = ((Integer ) this.fixedInterceptorMap.get(key)).intValue(); 799 return (index + fixedInterceptorOffset); 800 } 801 else { 802 if (logger.isDebugEnabled()) { 803 logger.debug("Unable to apply any optimisations to advised method: " + method); 804 } 805 return AOP_PROXY; 806 } 807 } 808 else { 809 if (exposeProxy || !isStatic) { 816 return INVOKE_TARGET; 817 } 818 Class returnType = method.getReturnType(); 819 if (targetClass == returnType) { 820 if (logger.isDebugEnabled()) { 821 logger.debug("Method " + method + 822 "has return type same as target type (may return this) - using INVOKE_TARGET"); 823 } 824 return INVOKE_TARGET; 825 } 826 else if (returnType.isPrimitive() || !returnType.isAssignableFrom(targetClass)) { 827 if (logger.isDebugEnabled()) { 828 logger.debug("Method " + method + 829 " has return type that ensures this cannot be returned- using DISPATCH_TARGET"); 830 } 831 return DISPATCH_TARGET; 832 } 833 else { 834 if (logger.isDebugEnabled()) { 835 logger.debug("Method " + method + 836 "has return type that is assignable from the target type (may return this) - " + 837 "using INVOKE_TARGET"); 838 } 839 return INVOKE_TARGET; 840 } 841 } 842 } 843 844 public boolean equals(Object other) { 845 if (other == this) { 846 return true; 847 } 848 if (!(other instanceof ProxyCallbackFilter)) { 849 return false; 850 } 851 ProxyCallbackFilter otherCallbackFilter = (ProxyCallbackFilter) other; 852 if (this.advised.isFrozen() != otherCallbackFilter.advised.isFrozen()) { 853 return false; 854 } 855 if (this.advised.isExposeProxy() != otherCallbackFilter.advised.isExposeProxy()) { 856 return false; 857 } 858 if (this.advised.getTargetSource().isStatic() != 859 otherCallbackFilter.advised.getTargetSource().isStatic()) { 860 return false; 861 } 862 if (!AopProxyUtils.equalsProxiedInterfaces(this.advised, otherCallbackFilter.advised)) { 863 return false; 864 } 865 Advisor[] thisAdvisors = this.advised.getAdvisors(); 868 Advisor[] thatAdvisors = otherCallbackFilter.advised.getAdvisors(); 869 if (thisAdvisors.length != thatAdvisors.length) { 870 return false; 871 } 872 for (int i = 0; i < thisAdvisors.length; i++) { 873 Advisor thisAdvisor = thisAdvisors[i]; 874 Advisor thatAdvisor = thatAdvisors[i]; 875 if (!equalsAdviceClasses(thisAdvisor, thatAdvisor)) { 876 return false; 877 } 878 if (!equalsPointcuts(thisAdvisor, thatAdvisor)) { 879 return false; 880 } 881 } 882 return true; 883 } 884 885 private boolean equalsAdviceClasses(Advisor a, Advisor b) { 886 Advice aa = a.getAdvice(); 887 Advice ba = b.getAdvice(); 888 if (aa == null || ba == null) { 889 return (aa == ba); 890 } 891 return aa.getClass().equals(ba.getClass()); 892 } 893 894 private boolean equalsPointcuts(Advisor a, Advisor b) { 895 return (a instanceof PointcutAdvisor && b instanceof PointcutAdvisor && 896 ObjectUtils.nullSafeEquals(((PointcutAdvisor) a).getPointcut(), ((PointcutAdvisor) b).getPointcut())); 897 } 898 899 public int hashCode() { 900 int hashCode = 0; 901 Advisor[] advisors = this.advised.getAdvisors(); 902 for (int i = 0; i < advisors.length; i++) { 903 Advice advice = advisors[i].getAdvice(); 904 if (advice != null) { 905 hashCode = 13 * hashCode + advice.getClass().hashCode(); 906 } 907 } 908 hashCode = 13 * hashCode + (this.advised.isFrozen() ? 1 : 0); 909 hashCode = 13 * hashCode + (this.advised.isExposeProxy() ? 1 : 0); 910 hashCode = 13 * hashCode + (this.advised.isOptimize() ? 1 : 0); 911 hashCode = 13 * hashCode + (this.advised.isOpaque() ? 1 : 0); 912 return hashCode; 913 } 914 } 915 916 } 917 | Popular Tags |