Skip to content

Commit cb78260

Browse files
committed
DATAREST-684 - ProxyProjectionFactory now exposes target instance on proxy.
Changed TargetClassAware to TargetAware and expose the actual proxy target for framework purposes.
1 parent 9977c61 commit cb78260

File tree

3 files changed

+72
-24
lines changed

3 files changed

+72
-24
lines changed

src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java

+16-24
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import org.springframework.beans.BeanUtils;
3030
import org.springframework.util.Assert;
3131

32-
import com.fasterxml.jackson.annotation.JsonIgnore;
33-
3432
/**
3533
* A {@link ProjectionFactory} to create JDK proxies to back interfaces and handle method invocations on them. By
3634
* default accessor methods are supported. In case the delegating lookups result in an object of different type that the
@@ -64,13 +62,13 @@ public <T> T createProjection(Class<T> projectionType, Object source) {
6462
ProxyFactory factory = new ProxyFactory();
6563
factory.setTarget(source);
6664
factory.setOpaque(true);
67-
factory.setInterfaces(projectionType, TargetClassAware.class);
65+
factory.setInterfaces(projectionType, TargetAware.class);
6866

6967
if (IS_JAVA_8) {
7068
factory.addAdvice(new DefaultMethodInvokingMethodInterceptor());
7169
}
7270

73-
factory.addAdvice(new TargetClassAwareMethodInterceptor(source.getClass()));
71+
factory.addAdvice(new TargetAwareMethodInterceptor(source.getClass()));
7472
factory.addAdvice(getMethodInterceptor(source, projectionType));
7573

7674
return (T) factory.getProxy(getClass().getClassLoader());
@@ -152,45 +150,37 @@ protected boolean isInputProperty(PropertyDescriptor descriptor) {
152150
return true;
153151
}
154152

155-
/**
156-
* Extension of {@link org.springframework.aop.TargetClassAware} to be able to ignore the getter on JSON rendering.
157-
*
158-
* @author Oliver Gierke
159-
*/
160-
public static interface TargetClassAware extends org.springframework.aop.TargetClassAware {
161-
162-
@JsonIgnore
163-
Class<?> getTargetClass();
164-
}
165-
166153
/**
167154
* Custom {@link MethodInterceptor} to expose the proxy target class even if we set
168155
* {@link ProxyFactory#setOpaque(boolean)} to true to prevent properties on {@link Advised} to be rendered.
169156
*
170157
* @author Oliver Gierke
171158
*/
172-
private static class TargetClassAwareMethodInterceptor implements MethodInterceptor {
159+
private static class TargetAwareMethodInterceptor implements MethodInterceptor {
173160

174161
private static final Method GET_TARGET_CLASS_METHOD;
175-
private final Class<?> targetClass;
162+
private static final Method GET_TARGET_METHOD;
163+
164+
private final Class<?> targetType;
176165

177166
static {
178167
try {
179-
GET_TARGET_CLASS_METHOD = TargetClassAware.class.getMethod("getTargetClass");
168+
GET_TARGET_CLASS_METHOD = TargetAware.class.getMethod("getTargetClass");
169+
GET_TARGET_METHOD = TargetAware.class.getMethod("getTarget");
180170
} catch (NoSuchMethodException e) {
181171
throw new IllegalStateException(e);
182172
}
183173
}
184174

185175
/**
186-
* Creates a new {@link TargetClassAwareMethodInterceptor} with the given target class.
176+
* Creates a new {@link TargetAwareMethodInterceptor} with the given target class.
187177
*
188-
* @param targetClass must not be {@literal null}.
178+
* @param targetType must not be {@literal null}.
189179
*/
190-
public TargetClassAwareMethodInterceptor(Class<?> targetClass) {
180+
public TargetAwareMethodInterceptor(Class<?> targetType) {
191181

192-
Assert.notNull(targetClass, "Target class must not be null!");
193-
this.targetClass = targetClass;
182+
Assert.notNull(targetType, "Target type must not be null!");
183+
this.targetType = targetType;
194184
}
195185

196186
/*
@@ -201,7 +191,9 @@ public TargetClassAwareMethodInterceptor(Class<?> targetClass) {
201191
public Object invoke(MethodInvocation invocation) throws Throwable {
202192

203193
if (invocation.getMethod().equals(GET_TARGET_CLASS_METHOD)) {
204-
return targetClass;
194+
return targetType;
195+
} else if (invocation.getMethod().equals(GET_TARGET_METHOD)) {
196+
return invocation.getThis();
205197
}
206198

207199
return invocation.proceed();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.projection;
17+
18+
import org.springframework.aop.RawTargetAccess;
19+
20+
import com.fasterxml.jackson.annotation.JsonIgnore;
21+
22+
/**
23+
* Extension of {@link org.springframework.aop.TargetClassAware} to be able to ignore the getter on JSON rendering.
24+
*
25+
* @author Oliver Gierke
26+
*/
27+
public interface TargetAware extends org.springframework.aop.TargetClassAware, RawTargetAccess {
28+
29+
/**
30+
* Returns the type of the proxy target.
31+
*
32+
* @return will never be {@literal null}.
33+
*/
34+
@JsonIgnore
35+
Class<?> getTargetClass();
36+
37+
/**
38+
* Returns the proxy target.
39+
*
40+
* @return will never be {@literal null}.
41+
*/
42+
@JsonIgnore
43+
Object getTarget();
44+
}

src/test/java/org/springframework/data/projection/ProxyProjectionFactoryUnitTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,18 @@ public void invokesDefaultMethodOnProxy() {
176176
assertThat(advisors[0].getAdvice(), is(instanceOf(DefaultMethodInvokingMethodInterceptor.class)));
177177
}
178178

179+
/**
180+
* @see DATACMNS-648
181+
*/
182+
@Test
183+
public void exposesProxyTarget() {
184+
185+
CustomerExcerpt excerpt = factory.createProjection(CustomerExcerpt.class);
186+
187+
assertThat(excerpt, is(instanceOf(TargetAware.class)));
188+
assertThat(((TargetAware) excerpt).getTarget(), is(instanceOf(Map.class)));
189+
}
190+
179191
static class Customer {
180192

181193
public String firstname, lastname;

0 commit comments

Comments
 (0)