001package ball.lang.reflect; 002/*- 003 * ########################################################################## 004 * Utilities 005 * %% 006 * Copyright (C) 2008 - 2022 Allen D. Ball 007 * %% 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 * ########################################################################## 020 */ 021import java.lang.reflect.Method; 022import lombok.Getter; 023import lombok.RequiredArgsConstructor; 024import lombok.ToString; 025 026import static org.apache.commons.lang3.reflect.MethodUtils.invokeMethod; 027 028/** 029 * "Intercepting" {@link java.lang.reflect.InvocationHandler} 030 * implementation. 031 * 032 * @param <T> The type of the "wrapped" target. 033 * 034 * {@bean.info} 035 * 036 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 037 */ 038@RequiredArgsConstructor @ToString 039public class InterceptingInvocationHandler<T> extends DefaultInvocationHandler { 040 @Getter private final T target; 041 042 /** 043 * Subclasses may declare methods with the same signature of a proxied 044 * interface method which will be invoked (as a sort of listener) before 045 * invoking the target method. If the invoked {@link Method}'s 046 * declaring class is assignable from the target's class, the 047 * {@link Method} is invoked on the target. 048 * 049 * @param proxy The proxy instance. 050 * @param method The {@link Method}. 051 * @param argv The argument array. 052 * 053 * @return The value to return from the {@link Method} invocation. 054 * 055 * @throws Exception If the {@link Method} cannot be invoked. 056 */ 057 @Override 058 public Object invoke(Object proxy, Method method, Object[] argv) throws Throwable { 059 try { 060 invokeMethod(this, true, method.getName(), argv, method.getParameterTypes()); 061 } catch (Exception exception) { 062 } 063 064 Object result = null; 065 066 if (method.isDefault()) { 067 result = super.invoke(proxy, method, argv); 068 } else if (method.getDeclaringClass().isAssignableFrom(target.getClass())) { 069 result = method.invoke(target, argv); 070 } else { 071 result = super.invoke(proxy, method, argv); 072 } 073 074 return result; 075 } 076}