@Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) { if (getControllerMethod.equals(method)) { return this.controllerMethod; } else if (getArgumentValues.equals(method)) { return this.argumentValues; } else if (ReflectionUtils.isObjectMethod(method)) { return ReflectionUtils.invokeMethod(method, obj, args); } else { this.controllerMethod = method; this.argumentValues = args; Class<?> returnType = method.getReturnType(); return (void.class.equals(returnType) ? null : returnType.cast(initProxy(returnType, this))); } }
/** * Wrap the given delegate {@link BeanInfo} instance and find any non-void returning setter * methods, creating and adding a {@link PropertyDescriptor} for each. * * <p>The wrapped {@code BeanInfo} is not modified in any way by this process. * * @see #getPropertyDescriptors() * @throws IntrospectionException if any problems occur creating and adding new {@code * PropertyDescriptors} */ public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException { this.delegate = delegate; // PropertyDescriptor instances from the delegate object are never added directly, but always // copied to the local collection of #propertyDescriptors and returned by calls to // #getPropertyDescriptors(). this algorithm iterates through all methods (method descriptors) // in the wrapped BeanInfo object, copying any existing PropertyDescriptor or creating a new // one for any non-standard setter methods found. ALL_METHODS: for (MethodDescriptor md : delegate.getMethodDescriptors()) { Method method = md.getMethod(); // bypass non-getter java.lang.Class methods for efficiency if (ReflectionUtils.isObjectMethod(method) && !method.getName().startsWith("get")) { continue ALL_METHODS; } // is the method a NON-INDEXED setter? ignore return type in order to capture non-void // signatures if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) { String propertyName = propertyNameFor(method); if (propertyName.length() == 0) { continue ALL_METHODS; } for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) { Method readMethod = pd.getReadMethod(); Method writeMethod = pd.getWriteMethod(); // has the setter already been found by the wrapped BeanInfo? if (writeMethod != null && writeMethod.getName().equals(method.getName())) { // yes -> copy it, including corresponding getter method (if any -- may be null) this.addOrUpdatePropertyDescriptor(propertyName, readMethod, writeMethod); continue ALL_METHODS; } // has a getter corresponding to this setter already been found by the wrapped BeanInfo? if (readMethod != null && readMethod.getName().equals(getterMethodNameFor(propertyName)) && readMethod.getReturnType().equals(method.getParameterTypes()[0])) { this.addOrUpdatePropertyDescriptor(propertyName, readMethod, method); continue ALL_METHODS; } } // the setter method was not found by the wrapped BeanInfo -> add a new PropertyDescriptor // for it // no corresponding getter was detected, so the 'read method' parameter is null. this.addOrUpdatePropertyDescriptor(propertyName, null, method); continue ALL_METHODS; } // is the method an INDEXED setter? ignore return type in order to capture non-void signatures if (method.getName().startsWith("set") && method.getParameterTypes().length == 2 && method.getParameterTypes()[0].equals(int.class)) { String propertyName = propertyNameFor(method); if (propertyName.length() == 0) { continue ALL_METHODS; } DELEGATE_PD: for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) { if (!(pd instanceof IndexedPropertyDescriptor)) { continue DELEGATE_PD; } IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; Method readMethod = ipd.getReadMethod(); Method writeMethod = ipd.getWriteMethod(); Method indexedReadMethod = ipd.getIndexedReadMethod(); Method indexedWriteMethod = ipd.getIndexedWriteMethod(); // has the setter already been found by the wrapped BeanInfo? if (indexedWriteMethod != null && indexedWriteMethod.getName().equals(method.getName())) { // yes -> copy it, including corresponding getter method (if any -- may be null) this.addOrUpdatePropertyDescriptor( propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod); continue ALL_METHODS; } // has a getter corresponding to this setter already been found by the wrapped BeanInfo? if (indexedReadMethod != null && indexedReadMethod.getName().equals(getterMethodNameFor(propertyName)) && indexedReadMethod.getReturnType().equals(method.getParameterTypes()[1])) { this.addOrUpdatePropertyDescriptor( propertyName, readMethod, writeMethod, indexedReadMethod, method); continue ALL_METHODS; } } // the INDEXED setter method was not found by the wrapped BeanInfo -> add a new // PropertyDescriptor // for it. no corresponding INDEXED getter was detected, so the 'indexed read method' // parameter is null. this.addOrUpdatePropertyDescriptor(propertyName, null, null, null, method); continue ALL_METHODS; } // the method is not a setter, but is it a getter? for (PropertyDescriptor pd : delegate.getPropertyDescriptors()) { // have we already copied this read method to a property descriptor locally? for (PropertyDescriptor existingPD : this.propertyDescriptors) { if (method.equals(pd.getReadMethod()) && existingPD.getName().equals(pd.getName())) { if (existingPD.getReadMethod() == null) { // no -> add it now this.addOrUpdatePropertyDescriptor(pd.getName(), method, pd.getWriteMethod()); } // yes -> do not add a duplicate continue ALL_METHODS; } } if (method == pd.getReadMethod() || (pd instanceof IndexedPropertyDescriptor && method == ((IndexedPropertyDescriptor) pd).getIndexedReadMethod())) { // yes -> copy it, including corresponding setter method (if any -- may be null) if (pd instanceof IndexedPropertyDescriptor) { this.addOrUpdatePropertyDescriptor( pd.getName(), pd.getReadMethod(), pd.getWriteMethod(), ((IndexedPropertyDescriptor) pd).getIndexedReadMethod(), ((IndexedPropertyDescriptor) pd).getIndexedWriteMethod()); } else { this.addOrUpdatePropertyDescriptor( pd.getName(), pd.getReadMethod(), pd.getWriteMethod()); } continue ALL_METHODS; } } } }