1
16 package org.springframework.data.web;
17
18 import java.util.Arrays;
19 import java.util.List;
20
21 import org.springframework.beans.BeansException;
22 import org.springframework.beans.MutablePropertyValues;
23 import org.springframework.beans.factory.BeanClassLoaderAware;
24 import org.springframework.beans.factory.BeanFactory;
25 import org.springframework.beans.factory.BeanFactoryAware;
26 import org.springframework.beans.factory.ObjectFactory;
27 import org.springframework.core.MethodParameter;
28 import org.springframework.core.annotation.AnnotatedElementUtils;
29 import org.springframework.core.convert.ConversionService;
30 import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
31 import org.springframework.util.ClassUtils;
32 import org.springframework.web.bind.WebDataBinder;
33 import org.springframework.web.bind.support.WebDataBinderFactory;
34 import org.springframework.web.context.request.NativeWebRequest;
35 import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
36 import org.springframework.web.method.support.HandlerMethodArgumentResolver;
37
38
44 public class ProxyingHandlerMethodArgumentResolver extends ModelAttributeMethodProcessor
45 implements BeanFactoryAware, BeanClassLoaderAware {
46
47 private static final List<String> IGNORED_PACKAGES = Arrays.asList("java", "org.springframework");
48
49 private final SpelAwareProxyProjectionFactory proxyFactory;
50 private final ObjectFactory<ConversionService> conversionService;
51
52
57 public ProxyingHandlerMethodArgumentResolver(ObjectFactory<ConversionService> conversionService,
58 boolean annotationNotRequired) {
59
60 super(annotationNotRequired);
61
62 this.proxyFactory = new SpelAwareProxyProjectionFactory();
63 this.conversionService = conversionService;
64 }
65
66
70 @Override
71 public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
72 this.proxyFactory.setBeanFactory(beanFactory);
73 }
74
75
79 @Override
80 public void setBeanClassLoader(ClassLoader classLoader) {
81 this.proxyFactory.setBeanClassLoader(classLoader);
82 }
83
84
88 @Override
89 public boolean supportsParameter(MethodParameter parameter) {
90
91 if (!super.supportsParameter(parameter)) {
92 return false;
93 }
94
95 Class<?> type = parameter.getParameterType();
96
97 if (!type.isInterface()) {
98 return false;
99 }
100
101
102 if (parameter.getParameterAnnotation(ProjectedPayload.class) != null) {
103 return true;
104 }
105
106
107 if (AnnotatedElementUtils.findMergedAnnotation(type, ProjectedPayload.class) != null) {
108 return true;
109 }
110
111
112 String packageName = ClassUtils.getPackageName(type);
113
114 return !IGNORED_PACKAGES.stream().anyMatch(it -> packageName.startsWith(it));
115 }
116
117
121 @Override
122 protected Object createAttribute(String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory,
123 NativeWebRequest request) throws Exception {
124
125 MapDataBinder binder = new MapDataBinder(parameter.getParameterType(), conversionService.getObject());
126 binder.bind(new MutablePropertyValues(request.getParameterMap()));
127
128 return proxyFactory.createProjection(parameter.getParameterType(), binder.getTarget());
129 }
130
131
135 @Override
136 protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {}
137 }
138