|
26 | 26 | import java.util.Set;
|
27 | 27 | import java.util.WeakHashMap;
|
28 | 28 |
|
29 |
| -import org.aopalliance.aop.Advice; |
30 | 29 | import org.aopalliance.intercept.MethodInvocation;
|
31 | 30 | import org.apache.commons.logging.Log;
|
32 | 31 | import org.apache.commons.logging.LogFactory;
|
33 | 32 |
|
34 |
| -import org.springframework.aop.Advisor; |
35 | 33 | import org.springframework.aop.AopInvocationException;
|
36 |
| -import org.springframework.aop.PointcutAdvisor; |
37 | 34 | import org.springframework.aop.RawTargetAccess;
|
38 | 35 | import org.springframework.aop.TargetSource;
|
39 | 36 | import org.springframework.aop.support.AopUtils;
|
@@ -205,12 +202,21 @@ private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly)
|
205 | 202 | types[x] = callbacks[x].getClass();
|
206 | 203 | }
|
207 | 204 | // fixedInterceptorMap only populated at this point, after getCallbacks call above
|
208 |
| - enhancer.setCallbackFilter(new ProxyCallbackFilter( |
209 |
| - this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); |
| 205 | + ProxyCallbackFilter filter = new ProxyCallbackFilter( |
| 206 | + this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset); |
| 207 | + enhancer.setCallbackFilter(filter); |
210 | 208 | enhancer.setCallbackTypes(types);
|
211 | 209 |
|
212 | 210 | // Generate the proxy class and create a proxy instance.
|
213 |
| - return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks)); |
| 211 | + // ProxyCallbackFilter has method introspection capability with Advisor access. |
| 212 | + try { |
| 213 | + return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks)); |
| 214 | + } |
| 215 | + finally { |
| 216 | + // Reduce ProxyCallbackFilter to key-only state for its class cache role |
| 217 | + // in the CGLIB$CALLBACK_FILTER field, not leaking any Advisor state... |
| 218 | + filter.advised.reduceToAdvisorKey(); |
| 219 | + } |
214 | 220 | }
|
215 | 221 | catch (CodeGenerationException | IllegalArgumentException ex) {
|
216 | 222 | throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
|
@@ -294,9 +300,9 @@ else if (logger.isDebugEnabled() && !Modifier.isPublic(mod) && !Modifier.isProte
|
294 | 300 |
|
295 | 301 | private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
|
296 | 302 | // Parameters used for optimization choices...
|
297 |
| - boolean exposeProxy = this.advised.isExposeProxy(); |
298 |
| - boolean isFrozen = this.advised.isFrozen(); |
299 | 303 | boolean isStatic = this.advised.getTargetSource().isStatic();
|
| 304 | + boolean isFrozen = this.advised.isFrozen(); |
| 305 | + boolean exposeProxy = this.advised.isExposeProxy(); |
300 | 306 |
|
301 | 307 | // Choose an "aop" interceptor (used for AOP calls).
|
302 | 308 | Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
|
@@ -776,7 +782,7 @@ public Object proceed() throws Throwable {
|
776 | 782 | */
|
777 | 783 | private static class ProxyCallbackFilter implements CallbackFilter {
|
778 | 784 |
|
779 |
| - private final AdvisedSupport advised; |
| 785 | + final AdvisedSupport advised; |
780 | 786 |
|
781 | 787 | private final Map<Method, Integer> fixedInterceptorMap;
|
782 | 788 |
|
@@ -857,9 +863,9 @@ public int accept(Method method) {
|
857 | 863 | // Proxy is not yet available, but that shouldn't matter.
|
858 | 864 | List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
|
859 | 865 | boolean haveAdvice = !chain.isEmpty();
|
860 |
| - boolean exposeProxy = this.advised.isExposeProxy(); |
861 | 866 | boolean isStatic = this.advised.getTargetSource().isStatic();
|
862 | 867 | boolean isFrozen = this.advised.isFrozen();
|
| 868 | + boolean exposeProxy = this.advised.isExposeProxy(); |
863 | 869 | if (haveAdvice || !isFrozen) {
|
864 | 870 | // If exposing the proxy, then AOP_PROXY must be used.
|
865 | 871 | if (exposeProxy) {
|
@@ -921,63 +927,18 @@ public boolean equals(@Nullable Object other) {
|
921 | 927 | return false;
|
922 | 928 | }
|
923 | 929 | AdvisedSupport otherAdvised = otherCallbackFilter.advised;
|
924 |
| - if (this.advised.isFrozen() != otherAdvised.isFrozen()) { |
925 |
| - return false; |
926 |
| - } |
927 |
| - if (this.advised.isExposeProxy() != otherAdvised.isExposeProxy()) { |
928 |
| - return false; |
929 |
| - } |
930 |
| - if (this.advised.getTargetSource().isStatic() != otherAdvised.getTargetSource().isStatic()) { |
931 |
| - return false; |
932 |
| - } |
933 |
| - if (!AopProxyUtils.equalsProxiedInterfaces(this.advised, otherAdvised)) { |
934 |
| - return false; |
935 |
| - } |
936 |
| - // Advice instance identity is unimportant to the proxy class: |
937 |
| - // All that matters is type and ordering. |
938 |
| - if (this.advised.getAdvisorCount() != otherAdvised.getAdvisorCount()) { |
939 |
| - return false; |
940 |
| - } |
941 |
| - Advisor[] thisAdvisors = this.advised.getAdvisors(); |
942 |
| - Advisor[] thatAdvisors = otherAdvised.getAdvisors(); |
943 |
| - for (int i = 0; i < thisAdvisors.length; i++) { |
944 |
| - Advisor thisAdvisor = thisAdvisors[i]; |
945 |
| - Advisor thatAdvisor = thatAdvisors[i]; |
946 |
| - if (!equalsAdviceClasses(thisAdvisor, thatAdvisor)) { |
947 |
| - return false; |
948 |
| - } |
949 |
| - if (!equalsPointcuts(thisAdvisor, thatAdvisor)) { |
950 |
| - return false; |
951 |
| - } |
952 |
| - } |
953 |
| - return true; |
954 |
| - } |
955 |
| - |
956 |
| - private static boolean equalsAdviceClasses(Advisor a, Advisor b) { |
957 |
| - return (a.getAdvice().getClass() == b.getAdvice().getClass()); |
958 |
| - } |
959 |
| - |
960 |
| - private static boolean equalsPointcuts(Advisor a, Advisor b) { |
961 |
| - // If only one of the advisor (but not both) is PointcutAdvisor, then it is a mismatch. |
962 |
| - // Takes care of the situations where an IntroductionAdvisor is used (see SPR-3959). |
963 |
| - return (!(a instanceof PointcutAdvisor pointcutAdvisor1) || |
964 |
| - (b instanceof PointcutAdvisor pointcutAdvisor2 && |
965 |
| - ObjectUtils.nullSafeEquals(pointcutAdvisor1.getPointcut(), pointcutAdvisor2.getPointcut()))); |
| 930 | + return (this.advised.getAdvisorKey().equals(otherAdvised.getAdvisorKey()) && |
| 931 | + AopProxyUtils.equalsProxiedInterfaces(this.advised, otherAdvised) && |
| 932 | + ObjectUtils.nullSafeEquals(this.advised.getTargetClass(), otherAdvised.getTargetClass()) && |
| 933 | + this.advised.getTargetSource().isStatic() == otherAdvised.getTargetSource().isStatic() && |
| 934 | + this.advised.isFrozen() == otherAdvised.isFrozen() && |
| 935 | + this.advised.isExposeProxy() == otherAdvised.isExposeProxy() && |
| 936 | + this.advised.isOpaque() == otherAdvised.isOpaque()); |
966 | 937 | }
|
967 | 938 |
|
968 | 939 | @Override
|
969 | 940 | public int hashCode() {
|
970 |
| - int hashCode = 0; |
971 |
| - Advisor[] advisors = this.advised.getAdvisors(); |
972 |
| - for (Advisor advisor : advisors) { |
973 |
| - Advice advice = advisor.getAdvice(); |
974 |
| - hashCode = 13 * hashCode + advice.getClass().hashCode(); |
975 |
| - } |
976 |
| - hashCode = 13 * hashCode + (this.advised.isFrozen() ? 1 : 0); |
977 |
| - hashCode = 13 * hashCode + (this.advised.isExposeProxy() ? 1 : 0); |
978 |
| - hashCode = 13 * hashCode + (this.advised.isOptimize() ? 1 : 0); |
979 |
| - hashCode = 13 * hashCode + (this.advised.isOpaque() ? 1 : 0); |
980 |
| - return hashCode; |
| 941 | + return this.advised.getAdvisorKey().hashCode(); |
981 | 942 | }
|
982 | 943 | }
|
983 | 944 |
|
|
0 commit comments