Browse Source
Introduced ProxyUtils.getUserClass(…) that by default is basically a facade for Spring's ClassUtils.getUserClass(…) but allows the registration of ProxyDetector implementations via Spring's SpringFactoriesLoader mechanism. Moved all existing usages of ClassUtils.getUserClass(…) to ProxyUtils.pull/301/head
7 changed files with 192 additions and 10 deletions
@ -0,0 +1,108 @@
@@ -0,0 +1,108 @@
|
||||
/* |
||||
* Copyright 2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.util; |
||||
|
||||
import lombok.experimental.UtilityClass; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.ClassUtils; |
||||
import org.springframework.util.ConcurrentReferenceHashMap; |
||||
|
||||
/** |
||||
* Proxy type detection utilities, extensible via {@link ProxyDetector} registered via Spring factories. |
||||
* |
||||
* @author Oliver Gierke |
||||
* @soundtrack Victor Wooten - Cruising Altitude (Trypnotix) |
||||
*/ |
||||
@UtilityClass |
||||
public class ProxyUtils { |
||||
|
||||
private static Map<Class<?>, Class<?>> USER_TYPES = new ConcurrentReferenceHashMap<Class<?>, Class<?>>(); |
||||
|
||||
private static final List<ProxyDetector> DETECTORS = SpringFactoriesLoader.loadFactories(ProxyDetector.class, |
||||
ProxyUtils.class.getClassLoader()); |
||||
|
||||
static { |
||||
|
||||
DETECTORS.add(new ProxyDetector() { |
||||
|
||||
@Override |
||||
public Class<?> getUserType(Class<?> type) { |
||||
return ClassUtils.getUserClass(type); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Returns the user class for the given type. |
||||
* |
||||
* @param type must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Class<?> getUserClass(Class<?> type) { |
||||
|
||||
Assert.notNull(type, "Type must not be null!"); |
||||
|
||||
Class<?> result = USER_TYPES.get(type); |
||||
|
||||
if (result != null) { |
||||
return result; |
||||
} |
||||
|
||||
result = type; |
||||
|
||||
for (ProxyDetector proxyDetector : DETECTORS) { |
||||
result = proxyDetector.getUserType(result); |
||||
} |
||||
|
||||
USER_TYPES.put(type, result); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Returns the user class for the given source object. |
||||
* |
||||
* @param source must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Class<?> getUserClass(Object source) { |
||||
|
||||
Assert.notNull(source, "Source object must not be null!"); |
||||
|
||||
return getUserClass(source.getClass()); |
||||
} |
||||
|
||||
/** |
||||
* SPI to extend Spring's default proxy detection capabilities. |
||||
* |
||||
* @author Oliver Gierke |
||||
*/ |
||||
public interface ProxyDetector { |
||||
|
||||
/** |
||||
* Returns the user class for the given type. |
||||
* |
||||
* @param type will never be {@literal null}. |
||||
* @return |
||||
*/ |
||||
Class<?> getUserType(Class<?> type); |
||||
} |
||||
} |
||||
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
/* |
||||
* Copyright 2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.util; |
||||
|
||||
import static org.hamcrest.Matchers.*; |
||||
import static org.junit.Assert.*; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.aop.framework.ProxyFactory; |
||||
import org.springframework.data.util.ProxyUtils.ProxyDetector; |
||||
|
||||
/** |
||||
* Unit tests for {@link ProxyUtils}. |
||||
* |
||||
* @author Oliver Gierke |
||||
* @soundtrack Victor Wooten - The 13th Floor (Trypnotix) |
||||
*/ |
||||
public class ProxyUtilsUnitTests { |
||||
|
||||
@Test // DATACMNS-1324
|
||||
public void detectsStandardProxy() { |
||||
|
||||
ProxyFactory factory = new ProxyFactory(); |
||||
factory.setTarget(new Sample()); |
||||
Object proxy = factory.getProxy(); |
||||
|
||||
assertThat(proxy.getClass(), is(not((Class) Sample.class))); |
||||
assertThat(ProxyUtils.getUserClass(proxy), is(equalTo((Class) Sample.class))); |
||||
} |
||||
|
||||
@Test // DATACMNS-1324
|
||||
public void usesCustomProxyDetector() { |
||||
|
||||
ProxyFactory factory = new ProxyFactory(); |
||||
factory.setTarget(new AnotherSample()); |
||||
Object proxy = factory.getProxy(); |
||||
|
||||
assertThat(ProxyUtils.getUserClass(proxy), is(equalTo((Class) UserType.class))); |
||||
} |
||||
|
||||
static class SampleProxyDetector implements ProxyDetector { |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.util.ProxyUtils.ProxyDetector#getUserType(java.lang.Class) |
||||
*/ |
||||
@Override |
||||
public Class<?> getUserType(Class<?> type) { |
||||
return AnotherSample.class.isAssignableFrom(type) ? UserType.class : type; |
||||
} |
||||
} |
||||
|
||||
static class Sample {} |
||||
|
||||
static class UserType {} |
||||
|
||||
static class AnotherSample {} |
||||
} |
||||
@ -1 +1,2 @@
@@ -1 +1,2 @@
|
||||
org.springframework.data.web.config.SpringDataJacksonModules=org.springframework.data.web.config.SampleMixin |
||||
org.springframework.data.util.ProxyUtils$ProxyDetector=org.springframework.data.util.ProxyUtilsUnitTests$SampleProxyDetector |
||||
|
||||
Loading…
Reference in new issue