|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2020 the original author or authors. |
| 2 | + * Copyright 2002-2021 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
19 | 19 | import java.lang.reflect.Array;
|
20 | 20 | import java.lang.reflect.Method;
|
21 | 21 | import java.lang.reflect.Proxy;
|
| 22 | +import java.util.ArrayList; |
22 | 23 | import java.util.Arrays;
|
| 24 | +import java.util.List; |
23 | 25 |
|
24 | 26 | import org.springframework.aop.SpringProxy;
|
25 | 27 | import org.springframework.aop.TargetClassAware;
|
|
29 | 31 | import org.springframework.core.DecoratingProxy;
|
30 | 32 | import org.springframework.lang.Nullable;
|
31 | 33 | import org.springframework.util.Assert;
|
| 34 | +import org.springframework.util.ClassUtils; |
32 | 35 | import org.springframework.util.ObjectUtils;
|
| 36 | +import org.springframework.util.ReflectionUtils; |
33 | 37 |
|
34 | 38 | /**
|
35 | 39 | * Utility methods for AOP proxy factories.
|
|
44 | 48 | */
|
45 | 49 | public abstract class AopProxyUtils {
|
46 | 50 |
|
| 51 | + // JDK 17 Class.isSealed() method available? |
| 52 | + @Nullable |
| 53 | + private static final Method isSealedMethod = ClassUtils.getMethodIfAvailable(Class.class, "isSealed"); |
| 54 | + |
| 55 | + |
47 | 56 | /**
|
48 | 57 | * Obtain the singleton target object behind the given proxy, if any.
|
49 | 58 | * @param candidate the (potential) proxy to check
|
@@ -130,34 +139,23 @@ else if (Proxy.isProxyClass(targetClass)) {
|
130 | 139 | specifiedInterfaces = advised.getProxiedInterfaces();
|
131 | 140 | }
|
132 | 141 | }
|
133 |
| - boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class); |
134 |
| - boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class); |
135 |
| - boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)); |
136 |
| - int nonUserIfcCount = 0; |
137 |
| - if (addSpringProxy) { |
138 |
| - nonUserIfcCount++; |
139 |
| - } |
140 |
| - if (addAdvised) { |
141 |
| - nonUserIfcCount++; |
142 |
| - } |
143 |
| - if (addDecoratingProxy) { |
144 |
| - nonUserIfcCount++; |
| 142 | + List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3); |
| 143 | + for (Class<?> ifc : specifiedInterfaces) { |
| 144 | + // Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17) |
| 145 | + if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) { |
| 146 | + proxiedInterfaces.add(ifc); |
| 147 | + } |
145 | 148 | }
|
146 |
| - Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount]; |
147 |
| - System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length); |
148 |
| - int index = specifiedInterfaces.length; |
149 |
| - if (addSpringProxy) { |
150 |
| - proxiedInterfaces[index] = SpringProxy.class; |
151 |
| - index++; |
| 149 | + if (!advised.isInterfaceProxied(SpringProxy.class)) { |
| 150 | + proxiedInterfaces.add(SpringProxy.class); |
152 | 151 | }
|
153 |
| - if (addAdvised) { |
154 |
| - proxiedInterfaces[index] = Advised.class; |
155 |
| - index++; |
| 152 | + if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) { |
| 153 | + proxiedInterfaces.add(Advised.class); |
156 | 154 | }
|
157 |
| - if (addDecoratingProxy) { |
158 |
| - proxiedInterfaces[index] = DecoratingProxy.class; |
| 155 | + if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) { |
| 156 | + proxiedInterfaces.add(DecoratingProxy.class); |
159 | 157 | }
|
160 |
| - return proxiedInterfaces; |
| 158 | + return ClassUtils.toClassArray(proxiedInterfaces); |
161 | 159 | }
|
162 | 160 |
|
163 | 161 | /**
|
|
0 commit comments