MvcUriComponentsBuilder 和 ControllerMethodInvocationInterceptor的解读

 

ControllerMethodInvocationInterceptor实现了CGLIB的MethodInterceptor,所以是CGLIB动态代理的方法拦截器,从命名来看是对Controller的方法做了争强。同时也实现了org.aopalliance.intercept.MethodInterceptor

private static class ControllerMethodInvocationInterceptor implements MethodInterceptor, org.aopalliance.intercept.MethodInterceptor, MvcUriComponentsBuilder.MethodInvocationInfo {
        private final Class<?> controllerType;
        @Nullable
        private Method controllerMethod;
        @Nullable
        private Object[] argumentValues;

        ControllerMethodInvocationInterceptor(Class<?> controllerType) {
            this.controllerType = controllerType;
        }

        @Nullable
        public Object intercept(Object obj, Method method, Object[] args, @Nullable MethodProxy proxy) {
            if (method.getName().equals("getControllerType")) {
                return this.controllerType;
            } else if (method.getName().equals("getControllerMethod")) {
                return this.controllerMethod;
            } else if (method.getName().equals("getArgumentValues")) {
                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();

                try {
                    return returnType == Void.TYPE ? null : returnType.cast(initProxy(returnType, this));
                } catch (Throwable var7) {
                    throw new IllegalStateException("Failed to create proxy for controller method return type: " + method, var7);
                }
            }
        }

        @Nullable
        public Object invoke(MethodInvocation inv) throws Throwable {
            return this.intercept(inv.getThis(), inv.getMethod(), inv.getArguments(), (MethodProxy)null);
        }

        public Class<?> getControllerType() {
            return this.controllerType;
        }

        public Method getControllerMethod() {
            Assert.state(this.controllerMethod != null, "Not initialized yet");
            return this.controllerMethod;
        }

        public Object[] getArgumentValues() {
            Assert.state(this.argumentValues != null, "Not initialized yet");
            return this.argumentValues;
        }

        private static <T> T initProxy(Class<?> controllerType, @Nullable MvcUriComponentsBuilder.ControllerMethodInvocationInterceptor interceptor) {
            interceptor = interceptor != null ? interceptor : new MvcUriComponentsBuilder.ControllerMethodInvocationInterceptor(controllerType);
            if (controllerType == Object.class) {
                return interceptor;
            } else if (controllerType.isInterface()) {
                ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE);
                factory.addInterface(controllerType);
                factory.addInterface(MvcUriComponentsBuilder.MethodInvocationInfo.class);
                factory.addAdvice(interceptor);
                return factory.getProxy();
            } else {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(controllerType);
                enhancer.setInterfaces(new Class[]{MvcUriComponentsBuilder.MethodInvocationInfo.class});
                enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
                enhancer.setCallbackType(MethodInterceptor.class);
                Class<?> proxyClass = enhancer.createClass();
                Object proxy = null;
                if (MvcUriComponentsBuilder.objenesis.isWorthTrying()) {
                    try {
                        proxy = MvcUriComponentsBuilder.objenesis.newInstance(proxyClass, enhancer.getUseCache());
                    } catch (ObjenesisException var7) {
                        MvcUriComponentsBuilder.logger.debug("Failed to create controller proxy, falling back on default constructor", var7);
                    }
                }

                if (proxy == null) {
                    try {
                        proxy = ReflectionUtils.accessibleConstructor(proxyClass, new Class[0]).newInstance();
                    } catch (Throwable var6) {
                        throw new IllegalStateException("Failed to create controller proxy or use default constructor", var6);
                    }
                }

                ((Factory)proxy).setCallbacks(new Callback[]{interceptor});
                return proxy;
            }
        }
    }

    public interface MethodInvocationInfo {
        Class<?> getControllerType();

        Method getControllerMethod();

        Object[] getArgumentValues();
    }

 

参考文档:

发表评论