深入浅出设计模式(七):9.代理模式

9.代理模式(Proxy)

我们买房子办理贷款时可以自己到银行办理,但是手续很多,也可以找相应的代理公司,这样我们什么都不用管。代理模式就是给一个对象提供一个代理对象,由这个代理对象控制对原对象的引用

代理模式的实现原理

这里写图片描述

动态代理的实现

比如现有操作计算薪资、计算所得税、权限控制等,现系统要求给每个方法都使用日志记录,则每个操作就都要有一个日志记录的代理类,太多了,此时就可通过动态代理,代理类要都实现InvocationHandler接口。
这里写图片描述

SalaryInterface

// 计算薪资的接口  
public interface SalaryInterface {
    public void doSalary();
}

Salary

//计算薪资的实现类  
public class Salary implements SalaryInterface{
    public void doSalary() {
        System.out.println("进行薪资计算的逻辑处理");
    }
}

TaxInterface

//计算税率的接口  
public interface TaxInterface {
    public void doTax();
}

Tax

//计算税率的实现类  
public class Tax implements TaxInterface{
    public void doTax() {
        System.out.println("进行所得税计算的逻辑处理");
    }
}

TimeProxy

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//计算薪资和税率,并统计时间的代理类  
public class TimeProxy implements InvocationHandler{
    private Object obj; 
    //绑定代理对象
    public Object bind(Object obj) {
        this.obj = obj; 
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    /**
     * @description  每一个代理实例都必须指定一个调用处理器,代理对象调用方法时,该方法会指派到调用处理器的invoke()中去
     * @date  2016年1月14日
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = null;
        try { 
            long startTime = System.nanoTime(); // 获取开始时间
            result = method.invoke(obj, args);
            long endTime = System.nanoTime(); // 获取结束时间
            System.out.println("计算程序运行时间: " + (endTime - startTime) + "ns");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }   
}

Client

public class Client {
    public static void main (String[] args) {       
        TimeProxy timeProxy = new TimeProxy();
        SalaryInterface salaryInterface = (SalaryInterface)timeProxy.bind(new Salary());
        salaryInterface.doSalary();
        TaxInterface taxInterface = (TaxInterface)timeProxy.bind(new Tax());
        taxInterface.doTax();
    }
}

面向方面的程序编程

上面代码是记录程序的执行时间,若还需要记录其他内容,比如权限控制,此时要么修改原来的代理类,要么增加新的代理类,但这不符合面向对象的设计原则,那么有没有一种简单的方法既不增加代理类,也不修改原来代理类呢?具体实现可以参考AOP的实现原理

这里写图片描述

Advice

public interface Advice {
    public void before();
    public void after();
}

TimeAdvice

public class TimeAdvice implements Advice {
    long startTime;
    long endTime;
    @Override
    public void before() {
        startTime=System.nanoTime();   //获取开始时间
    }

    @Override
    public void after() {
        endTime=System.nanoTime(); //获取结束时间
        System.out.println("计算程序运行时间: "+(endTime-startTime)+"ns");
    }

MyProxy

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyProxy implements InvocationHandler{

    private Object obj;
    private Advice advice;

    //绑定代理对象
    public Object bind(Object obj, Advice advice) {
        this.obj = obj;
        this.advice = advice;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    //实现代理
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        try {
            advice.before();
            result = method.invoke(obj, args);
            advice.after();
        } catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }

}

ControlAdvice

public class ControlAdvice extends TimeAdvice {

    @Override
    public void before() {
        super.before();
        System.out.println("判断系统的权限 ");
    }

    @Override
    public void after() {
        super.after();
    }
}

此时若要在此基础上又加入权限控制,则可以增加一个Advice的实现类,继承TimeAdvice即可。

ControlAdvice

public class ControlAdvice extends TimeAdvice {

    @Override
    public void before() {
        super.before();
        System.out.println("判断系统的权限 ");
    }

    @Override
    public void after() {
        super.after();
    }
}

Client

public class Client {

    public static void main (String[] args) { 
        MyProxy timeProxy = new MyProxy();
        SalaryInterface salaryInterface = (SalaryInterface)timeProxy.bind(new Salary(), new ControlAdvice());
        salaryInterface.doSalary();
        TaxInterface taxInterface = (TaxInterface)timeProxy.bind(new Tax(), new ControlAdvice());
        taxInterface.doTax();
    }
}

AOP的意思是面向方面编程,AOP就是要分离那种和业务代码不相关的代码,通过另一种方式实现对业务代码的控制,而业务代码本身并不改变,这恰恰是代理模式的好时机,因为当系统对某个对象进行额外的控制的时候,就需要使用代理模式。

代理模式在Spring的实际应用

通过java的动态代理机制,就可以很容易实现AOP的思想。实际上Spring的AOP也是建立在JAVA的代理机制之上的。在Spring中主要是通过JdkDynamicAopProxy类实现动态代理的:

JdkDynamicAopProxy

package org.springframework.aop.framework;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AopInvocationException;
import org.springframework.aop.RawTargetAccess;
import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,
        Serializable {
    private static final long serialVersionUID = 5531744639992436476L;
    //记录日志
    private static Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
    //设定配置
    private final AdvisedSupport advised;
    private boolean equalsDefined;
    private boolean hashCodeDefined;

    public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if ((config.getAdvisors().length == 0)
                && (config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE)) {
            throw new AopConfigException(
                    "No advisors and no TargetSource specified");
        }
        this.advised = config;
    }

    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    //获取默认的代理类
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is "
                    + this.advised.getTargetSource());
        }
        Class[] proxiedInterfaces = AopProxyUtils
                .completeProxiedInterfaces(this.advised);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    private void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces) {
        for (Class proxiedInterface : proxiedInterfaces) {
            Method[] methods = proxiedInterface.getDeclaredMethods();
            for (Method method : methods) {
                if (AopUtils.isEqualsMethod(method)) {
                    this.equalsDefined = true;
                }
                if (AopUtils.isHashCodeMethod(method)) {
                    this.hashCodeDefined = true;
                }
                if ((this.equalsDefined) && (this.hashCodeDefined)) {
                    return;
                }
            }
        }
    }

    //反射调用
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        //设定源类
        TargetSource targetSource = this.advised.targetSource;
        Class targetClass = null;
        Object target = null;
        try {
            Object localObject1;
            //下列代码用于定义如何实现代理模式
            //判断是否为方法本身
            if ((!this.equalsDefined) && (AopUtils.isEqualsMethod(method))) {
                return Boolean.valueOf(equals(args[0]));
            }
            if ((!this.hashCodeDefined) && (AopUtils.isHashCodeMethod(method))) {
                return Integer.valueOf(hashCode());
            }
            if ((!this.advised.opaque)
                    && (method.getDeclaringClass().isInterface())
                    && (method.getDeclaringClass()
                            .isAssignableFrom(Advised.class))) {
                return AopUtils.invokeJoinpointUsingReflection(this.advised,
                        method, args);
            }
            if (this.advised.exposeProxy) {
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }
            //获取目标类
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }
            List<Object> chain = this.advised
                    .getInterceptorsAndDynamicInterceptionAdvice(method,
                            targetClass);
            Object retVal;
            Object retVal;
            //检查是否有拦截器
            if (chain.isEmpty()) {
                retVal = AopUtils.invokeJoinpointUsingReflection(target,
                        method, args);
            } else {
                MethodInvocation invocation = new ReflectiveMethodInvocation(
                        proxy, target, method, args, targetClass, chain);

                retVal = invocation.proceed();
            }
            Class<?> returnType = method.getReturnType();
            if ((retVal != null)
                    && (retVal == target)
                    && (returnType.isInstance(proxy))
                    && (!RawTargetAccess.class.isAssignableFrom(method
                            .getDeclaringClass()))) {
                retVal = proxy;
            } else if ((retVal == null) && (returnType != Void.TYPE)
                    && (returnType.isPrimitive())) {
                throw new AopInvocationException(
                        "Null return value from advice does not match primitive return type for: "
                                + method);
            }
            return retVal;
        } finally {
            if ((target != null) && (!targetSource.isStatic())) {
                targetSource.releaseTarget(target);
            }
            if (setProxyContext) {
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if (other == null) {
            return false;
        }
        JdkDynamicAopProxy otherProxy;
        if ((other instanceof JdkDynamicAopProxy)) {
            otherProxy = (JdkDynamicAopProxy) other;
        } else {
            JdkDynamicAopProxy otherProxy;
            if (Proxy.isProxyClass(other.getClass())) {
                InvocationHandler ih = Proxy.getInvocationHandler(other);
                if (!(ih instanceof JdkDynamicAopProxy)) {
                    return false;
                }
                otherProxy = (JdkDynamicAopProxy) ih;
            } else {
                return false;
            }
        }
        JdkDynamicAopProxy otherProxy;
        return AopProxyUtils.equalsInProxy(this.advised, otherProxy.advised);
    }

    public int hashCode() {
        return JdkDynamicAopProxy.class.hashCode() * 13
                + this.advised.getTargetSource().hashCode();
    }
}

ReflectiveMethodInvocation,主要负责调用代理类的方法

package org.springframework.aop.framework;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.BridgeMethodResolver;

public class ReflectiveMethodInvocation
  implements ProxyMethodInvocation, Cloneable
{
  protected final Object proxy;
  protected final Object target;
  protected final Method method;
  protected Object[] arguments;
  private final Class targetClass;
  private Map<String, Object> userAttributes;
  protected final List interceptorsAndDynamicMethodMatchers;
  private int currentInterceptorIndex = -1;

  protected ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] arguments, Class targetClass, List<Object> interceptorsAndDynamicMethodMatchers)
  {
    this.proxy = proxy;
    this.target = target;
    this.targetClass = targetClass;
    this.method = BridgeMethodResolver.findBridgedMethod(method);
    this.arguments = arguments;
    this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
  }

  //返回代理
  public final Object getProxy()
  {
    return this.proxy;
  }

  //返回目标类
  public final Object getThis()
  {
    return this.target;
  }

  public final AccessibleObject getStaticPart()
  {
    return this.method;
  }

  //返回方法
  public final Method getMethod()
  {
    return this.method;
  }

  //返回参数
  public final Object[] getArguments()
  {
    return this.arguments != null ? this.arguments : new Object[0];
  }

  public void setArguments(Object[] arguments)
  {
    this.arguments = arguments;
  }

  //调用方法
  public Object proceed()
    throws Throwable
  {
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();
    }
    Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if ((interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher))
    {
        //检查方法名是否匹配
      InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
      if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
        return dm.interceptor.invoke(this);
      }
      return proceed();
    }
    return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
  }

  //回调插入点
  protected Object invokeJoinpoint()
    throws Throwable
  {
    return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
  }

  public MethodInvocation invocableClone()
  {
    Object[] cloneArguments = null;
    if (this.arguments != null)
    {
      cloneArguments = new Object[this.arguments.length];
      System.arraycopy(this.arguments, 0, cloneArguments, 0, this.arguments.length);
    }
    return invocableClone(cloneArguments);
  }

  public MethodInvocation invocableClone(Object[] arguments)
  {
    if (this.userAttributes == null) {
      this.userAttributes = new HashMap();
    }
    try
    {
      ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation)clone();
      clone.arguments = arguments;
      return clone;
    }
    catch (CloneNotSupportedException ex)
    {
      throw new IllegalStateException("Should be able to clone object of type [" + getClass() + "]: " + ex);
    }
  }

  public void setUserAttribute(String key, Object value)
  {
    if (value != null)
    {
      if (this.userAttributes == null) {
        this.userAttributes = new HashMap();
      }
      this.userAttributes.put(key, value);
    }
    else if (this.userAttributes != null)
    {
      this.userAttributes.remove(key);
    }
  }

  //返回用户属性
  public Object getUserAttribute(String key)
  {
    return this.userAttributes != null ? this.userAttributes.get(key) : null;
  }

  public Map<String, Object> getUserAttributes()
  {
    if (this.userAttributes == null) {
      this.userAttributes = new HashMap();
    }
    return this.userAttributes;
  }

  //输出字符串流
  public String toString()
  {
    StringBuilder sb = new StringBuilder("ReflectiveMethodInvocation: ");
    sb.append(this.method).append("; ");
    if (this.target == null) {
      sb.append("target is null");
    } else {
      sb.append("target is of class [").append(this.target.getClass().getName()).append(']');
    }
    return sb.toString();
  }
}

DelegatingIntroductionInterceptor,主要负责委托拦截器

package org.springframework.aop.support;

import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.DynamicIntroductionAdvice;
import org.springframework.aop.IntroductionInterceptor;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.util.Assert;

public class DelegatingIntroductionInterceptor
  extends IntroductionInfoSupport
  implements IntroductionInterceptor
{
  private Object delegate;

  public DelegatingIntroductionInterceptor(Object delegate)
  {
    init(delegate);
  }

  protected DelegatingIntroductionInterceptor()
  {
    init(this);
  }

  private void init(Object delegate)
  {
    Assert.notNull(delegate, "Delegate must not be null");
    this.delegate = delegate;
    implementInterfacesOnObject(delegate);

    //控制接口
    suppressInterface(IntroductionInterceptor.class);
    suppressInterface(DynamicIntroductionAdvice.class);
  }

  //调用代理的方法
  public Object invoke(MethodInvocation mi)
    throws Throwable
  {
    if (isMethodOnIntroducedInterface(mi))
    {
      //直接调用代理方法
      Object retVal = AopUtils.invokeJoinpointUsingReflection(this.delegate, mi.getMethod(), mi.getArguments());
      if ((retVal == this.delegate) && ((mi instanceof ProxyMethodInvocation)))
      {
        Object proxy = ((ProxyMethodInvocation)mi).getProxy();
        //加入要代理的方法
        if (mi.getMethod().getReturnType().isInstance(proxy)) {
          retVal = proxy;
        }
      }
      return retVal;
    }
    return doProceed(mi);
  }

  protected Object doProceed(MethodInvocation mi)
    throws Throwable
  {
    return mi.proceed();
  }
}

Spring的proxy模式主要提现在AOP中,有两种代理方式,分别为JdkDynamicAopProxy和Cglib2AopProxy。下面再看看Cglib2AopProxy:

CglibAopProxy

package org.springframework.aop.framework;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.Advisor;
import org.springframework.aop.AopInvocationException;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.RawTargetAccess;
import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.core.CodeGenerationException;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;
import org.springframework.cglib.transform.impl.UndeclaredThrowableStrategy;
import org.springframework.core.SmartClassLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;

final class CglibAopProxy implements AopProxy, Serializable {
    private static final int AOP_PROXY = 0;
    private static final int INVOKE_TARGET = 1;
    private static final int NO_OVERRIDE = 2;
    private static final int DISPATCH_TARGET = 3;
    private static final int DISPATCH_ADVISED = 4;
    private static final int INVOKE_EQUALS = 5;
    private static final int INVOKE_HASHCODE = 6;
    protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
    private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap();
    protected final AdvisedSupport advised;
    private Object[] constructorArgs;
    private Class<?>[] constructorArgTypes;
    private final transient AdvisedDispatcher advisedDispatcher;
    private transient Map<String, Integer> fixedInterceptorMap;
    private transient int fixedInterceptorOffset;

    public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if ((config.getAdvisors().length == 0)
                && (config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE)) {
            throw new AopConfigException(
                    "No advisors and no TargetSource specified");
        }
        this.advised = config;
        this.advisedDispatcher = new AdvisedDispatcher(this.advised);
    }

    public void setConstructorArguments(Object[] constructorArgs,
            Class<?>[] constructorArgTypes) {
        if ((constructorArgs == null) || (constructorArgTypes == null)) {
            throw new IllegalArgumentException(
                    "Both 'constructorArgs' and 'constructorArgTypes' need to be specified");
        }
        if (constructorArgs.length != constructorArgTypes.length) {
            throw new IllegalArgumentException("Number of 'constructorArgs' ("
                    + constructorArgs.length
                    + ") must match number of 'constructorArgTypes' ("
                    + constructorArgTypes.length + ")");
        }
        this.constructorArgs = constructorArgs;
        this.constructorArgTypes = constructorArgTypes;
    }

    public Object getProxy() {
        return getProxy(null);
    }

    //获取具体的代理类
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is "
                    + this.advised.getTargetSource());
        }
        //获取代理
        try {
            Class<?> rootClass = this.advised.getTargetClass();
            Assert.state(rootClass != null,
                    "Target class must be available for creating a CGLIB proxy");

            Class<?> proxySuperClass = rootClass;
            //判断是否为cglibProxy代理
            if (ClassUtils.isCglibProxyClass(rootClass)) {
                proxySuperClass = rootClass.getSuperclass();
                Class<?>[] additionalInterfaces = rootClass.getInterfaces();
                for (Class<?> additionalInterface : additionalInterfaces) {
                    this.advised.addInterface(additionalInterface);
                }
            }
            //验证类
            validateClassIfNecessary(proxySuperClass);
            //配置CGLIB
            Enhancer enhancer = createEnhancer();
            if (classLoader != null) {
                enhancer.setClassLoader(classLoader);
                if (((classLoader instanceof SmartClassLoader))
                        && (((SmartClassLoader) classLoader)
                                .isClassReloadable(proxySuperClass))) {
                    enhancer.setUseCache(false);
                }
            }
            enhancer.setSuperclass(proxySuperClass);
            enhancer.setStrategy(new UndeclaredThrowableStrategy(
                    UndeclaredThrowableException.class));
            enhancer.setInterfaces(AopProxyUtils
                    .completeProxiedInterfaces(this.advised));
            enhancer.setInterceptDuringConstruction(false);
            //回调参数
            Callback[] callbacks = getCallbacks(rootClass);
            enhancer.setCallbacks(callbacks);
            enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised
                    .getConfigurationOnlyCopy(), this.fixedInterceptorMap,
                    this.fixedInterceptorOffset));
            //获取回调类型
            Class<?>[] types = new Class[callbacks.length];
            for (int x = 0; x < types.length; x++) {
                types[x] = callbacks[x].getClass();
            }
            enhancer.setCallbackTypes(types);
            //生成代理实例
            Object proxy;
            if (this.constructorArgs != null) {
                proxy = enhancer.create(this.constructorArgTypes,
                        this.constructorArgs);
            }
            //返回代理
            return enhancer.create();
        } catch (CodeGenerationException ex) {
            throw new AopConfigException(
                    "Could not generate CGLIB subclass of class ["
                            + this.advised.getTargetClass()
                            + "]: "
                            + "Common causes of this problem include using a final class or a non-visible class",
                    ex);
        } catch (IllegalArgumentException ex) {
            throw new AopConfigException(
                    "Could not generate CGLIB subclass of class ["
                            + this.advised.getTargetClass()
                            + "]: "
                            + "Common causes of this problem include using a final class or a non-visible class",
                    ex);
        } catch (Exception ex) {
            throw new AopConfigException("Unexpected AOP exception", ex);
        }
    }

    //创建代理Enhancer
    protected Enhancer createEnhancer() {
        return new Enhancer();
    }

    //检查是否支持代理
    private void validateClassIfNecessary(Class<?> proxySuperClass) {
        if (logger.isWarnEnabled()) {
            synchronized (validatedClasses) {
                if (!validatedClasses.containsKey(proxySuperClass)) {
                    doValidateClass(proxySuperClass);
                    validatedClasses.put(proxySuperClass, Boolean.TRUE);
                }
            }
        }
    }   

    private void doValidateClass(Class<?> proxySuperClass) {
        Method[] methods = proxySuperClass.getMethods();
        for (Method method : methods) {
            if ((!Object.class.equals(method.getDeclaringClass()))
                    && (Modifier.isFinal(method.getModifiers()))) {
                logger.warn("Unable to proxy method ["
                        + method
                        + "] because it is final: "
                        + "All calls to this method via a proxy will be routed directly to the proxy.");
            }
        }
    }

    //获取回调参数
    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
        boolean exposeProxy = this.advised.isExposeProxy();
        boolean isFrozen = this.advised.isFrozen();
        boolean isStatic = this.advised.getTargetSource().isStatic();

        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
        Callback targetInterceptor;
        Callback targetInterceptor;
        if (exposeProxy) {
            targetInterceptor = isStatic ? new StaticUnadvisedExposedInterceptor(
                    this.advised.getTargetSource().getTarget())
                    : new DynamicUnadvisedExposedInterceptor(
                            this.advised.getTargetSource());
        } else {
            targetInterceptor = isStatic ? new StaticUnadvisedInterceptor(
                    this.advised.getTargetSource().getTarget())
                    : new DynamicUnadvisedInterceptor(
                            this.advised.getTargetSource());
        }
        Callback targetDispatcher = (Callback) (isStatic ? new StaticDispatcher(
                this.advised.getTargetSource().getTarget())
                : new SerializableNoOp());

        Callback[] mainCallbacks = { aopInterceptor, targetInterceptor,
                new SerializableNoOp(), targetDispatcher,
                this.advisedDispatcher, new EqualsInterceptor(this.advised),
                new HashCodeInterceptor(this.advised) };
        Callback[] callbacks;
        if ((isStatic) && (isFrozen)) {
            Method[] methods = rootClass.getMethods();
            Callback[] fixedCallbacks = new Callback[methods.length];
            this.fixedInterceptorMap = new HashMap(methods.length);
            for (int x = 0; x < methods.length; x++) {
                List<Object> chain = this.advised
                        .getInterceptorsAndDynamicInterceptionAdvice(
                                methods[x], rootClass);
                fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                        chain, this.advised.getTargetSource().getTarget(),
                        this.advised.getTargetClass());
                this.fixedInterceptorMap.put(methods[x].toString(),
                        Integer.valueOf(x));
            }
            Callback[] callbacks = new Callback[mainCallbacks.length
                    + fixedCallbacks.length];
            System.arraycopy(mainCallbacks, 0, callbacks, 0,
                    mainCallbacks.length);
            System.arraycopy(fixedCallbacks, 0, callbacks,
                    mainCallbacks.length, fixedCallbacks.length);
            this.fixedInterceptorOffset = mainCallbacks.length;
        } else {
            callbacks = mainCallbacks;
        }
        return callbacks;
    }

    //返回消息
    private static Object processReturnType(Object proxy, Object target,
            Method method, Object retVal) {
        if ((retVal != null)
                && (retVal == target)
                && (!RawTargetAccess.class.isAssignableFrom(method
                        .getDeclaringClass()))) {
            retVal = proxy;
        }
        Class<?> returnType = method.getReturnType();
        if ((retVal == null) && (returnType != Void.TYPE)
                && (returnType.isPrimitive())) {
            throw new AopInvocationException(
                    "Null return value from advice does not match primitive return type for: "
                            + method);
        }
        return retVal;
    }

    public boolean equals(Object other) {
        return (this == other)
                || (((other instanceof CglibAopProxy)) && (AopProxyUtils
                        .equalsInProxy(this.advised,
                                ((CglibAopProxy) other).advised)));
    }

    public int hashCode() {
        return CglibAopProxy.class.hashCode() * 13
                + this.advised.getTargetSource().hashCode();
    }

    public static class SerializableNoOp implements NoOp, Serializable {
    }

    private static class StaticUnadvisedInterceptor implements
            MethodInterceptor, Serializable {
        private final Object target;

        public StaticUnadvisedInterceptor(Object target) {
            this.target = target;
        }

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            Object retVal = methodProxy.invoke(this.target, args);
            return CglibAopProxy.processReturnType(proxy, this.target, method,
                    retVal);
        }
    }

    private static class StaticUnadvisedExposedInterceptor implements
            MethodInterceptor, Serializable {
        private final Object target;

        public StaticUnadvisedExposedInterceptor(Object target) {
            this.target = target;
        }

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            try {
                oldProxy = AopContext.setCurrentProxy(proxy);
                Object retVal = methodProxy.invoke(this.target, args);
                return CglibAopProxy.processReturnType(proxy, this.target,
                        method, retVal);
            } finally {
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }

    //动态代理的具体事项
    private static class DynamicUnadvisedInterceptor implements
            MethodInterceptor, Serializable {
        //目标源
        private final TargetSource targetSource;

        public DynamicUnadvisedInterceptor(TargetSource targetSource) {
            this.targetSource = targetSource;
        }
        //代理方法 
        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            Object target = this.targetSource.getTarget();
            try {
                Object retVal = methodProxy.invoke(target, args);
                return CglibAopProxy.processReturnType(proxy, target, method,
                        retVal);
            } finally {
                this.targetSource.releaseTarget(target);
            }
        }
    }

    //实现AOP Alliance MethodInvocation
    private static class DynamicUnadvisedExposedInterceptor implements
            MethodInterceptor, Serializable {
        private final TargetSource targetSource;

        public DynamicUnadvisedExposedInterceptor(TargetSource targetSource) {
            this.targetSource = targetSource;
        }

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            Object target = this.targetSource.getTarget();
            try {
                oldProxy = AopContext.setCurrentProxy(proxy);
                Object retVal = methodProxy.invoke(target, args);
                return CglibAopProxy.processReturnType(proxy, target, method,
                        retVal);
            } finally {
                AopContext.setCurrentProxy(oldProxy);
                this.targetSource.releaseTarget(target);
            }
        }
    }

    private static class StaticDispatcher implements Dispatcher, Serializable {
        private Object target;

        public StaticDispatcher(Object target) {
            this.target = target;
        }

        public Object loadObject() {
            return this.target;
        }
    }

    private static class AdvisedDispatcher implements Dispatcher, Serializable {
        private final AdvisedSupport advised;

        public AdvisedDispatcher(AdvisedSupport advised) {
            this.advised = advised;
        }

        public Object loadObject() throws Exception {
            return this.advised;
        }
    }

    private static class EqualsInterceptor implements MethodInterceptor,
            Serializable {
        private final AdvisedSupport advised;

        public EqualsInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) {
            Object other = args[0];
            if (proxy == other) {
                return Boolean.valueOf(true);
            }
            if ((other instanceof Factory)) {
                Callback callback = ((Factory) other).getCallback(5);
                if (!(callback instanceof EqualsInterceptor)) {
                    return Boolean.valueOf(false);
                }
                AdvisedSupport otherAdvised = ((EqualsInterceptor) callback).advised;
                return Boolean.valueOf(AopProxyUtils.equalsInProxy(
                        this.advised, otherAdvised));
            }
            return Boolean.valueOf(false);
        }
    }

    private static class HashCodeInterceptor implements MethodInterceptor,
            Serializable {
        private final AdvisedSupport advised;

        public HashCodeInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) {
            return Integer.valueOf(CglibAopProxy.class.hashCode() * 13
                    + this.advised.getTargetSource().hashCode());
        }
    }

    private static class FixedChainStaticTargetInterceptor implements
            MethodInterceptor, Serializable {
        private final List<Object> adviceChain;
        private final Object target;
        private final Class<?> targetClass;

        public FixedChainStaticTargetInterceptor(List<Object> adviceChain,
                Object target, Class<?> targetClass) {
            this.adviceChain = adviceChain;
            this.target = target;
            this.targetClass = targetClass;
        }

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            MethodInvocation invocation = new CglibAopProxy.CglibMethodInvocation(
                    proxy, this.target, method, args, this.targetClass,
                    this.adviceChain, methodProxy);

            Object retVal = invocation.proceed();
            retVal = CglibAopProxy.processReturnType(proxy, this.target,
                    method, retVal);
            return retVal;
        }
    }

    private static class DynamicAdvisedInterceptor implements
            MethodInterceptor, Serializable {
        private AdvisedSupport advised;

        public DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            Object oldProxy = null;
            boolean setProxyContext = false;
            Class<?> targetClass = null;
            Object target = null;
            try {
                if (this.advised.exposeProxy) {
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                target = getTarget();
                if (target != null) {
                    targetClass = target.getClass();
                }
                List<Object> chain = this.advised
                        .getInterceptorsAndDynamicInterceptionAdvice(method,
                                targetClass);
                Object retVal;
                if ((chain.isEmpty())
                        && (Modifier.isPublic(method.getModifiers()))) {
                    retVal = methodProxy.invoke(target, args);
                } else {
                    retVal = new CglibAopProxy.CglibMethodInvocation(proxy,
                            target, method, args, targetClass, chain,
                            methodProxy).proceed();
                }
                Object retVal = CglibAopProxy.processReturnType(proxy, target,
                        method, retVal);
                return retVal;
            } finally {
                if (target != null) {
                    releaseTarget(target);
                }
                if (setProxyContext) {
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }

        public boolean equals(Object other) {
            if (this != other) {
                if (!(other instanceof DynamicAdvisedInterceptor)) {
                    break label33;
                }
            }
            label33: return this.advised
                    .equals(((DynamicAdvisedInterceptor) other).advised);
        }

        public int hashCode() {
            return this.advised.hashCode();
        }

        protected Object getTarget() throws Exception {
            return this.advised.getTargetSource().getTarget();
        }

        protected void releaseTarget(Object target) throws Exception {
            this.advised.getTargetSource().releaseTarget(target);
        }
    }

    private static class CglibMethodInvocation extends
            ReflectiveMethodInvocation {
        private final MethodProxy methodProxy;
        private boolean protectedMethod;

        public CglibMethodInvocation(Object proxy, Object target,
                Method method, Object[] arguments, Class<?> targetClass,
                List<Object> interceptorsAndDynamicMethodMatchers,
                MethodProxy methodProxy) {
            super(target, method, arguments, targetClass,
                    interceptorsAndDynamicMethodMatchers);
            this.methodProxy = methodProxy;
            this.protectedMethod = Modifier.isProtected(method.getModifiers());
        }

        protected Object invokeJoinpoint() throws Throwable {
            if (this.protectedMethod) {
                return super.invokeJoinpoint();
            }
            return this.methodProxy.invoke(this.target, this.arguments);
        }
    }

    private static class ProxyCallbackFilter implements CallbackFilter {
        private final AdvisedSupport advised;
        private final Map<String, Integer> fixedInterceptorMap;
        private final int fixedInterceptorOffset;

        public ProxyCallbackFilter(AdvisedSupport advised,
                Map<String, Integer> fixedInterceptorMap,
                int fixedInterceptorOffset) {
            this.advised = advised;
            this.fixedInterceptorMap = fixedInterceptorMap;
            this.fixedInterceptorOffset = fixedInterceptorOffset;
        }

        public int accept(Method method) {
            if (AopUtils.isFinalizeMethod(method)) {
                CglibAopProxy.logger
                        .debug("Found finalize() method - using NO_OVERRIDE");
                return 2;
            }
            if ((!this.advised.isOpaque())
                    && (method.getDeclaringClass().isInterface())
                    && (method.getDeclaringClass()
                            .isAssignableFrom(Advised.class))) {
                if (CglibAopProxy.logger.isDebugEnabled()) {
                    CglibAopProxy.logger
                            .debug("Method is declared on Advised interface: "
                                    + method);
                }
                return 4;
            }
            if (AopUtils.isEqualsMethod(method)) {
                CglibAopProxy.logger.debug("Found 'equals' method: " + method);
                return 5;
            }
            if (AopUtils.isHashCodeMethod(method)) {
                CglibAopProxy.logger
                        .debug("Found 'hashCode' method: " + method);
                return 6;
            }
            Class<?> targetClass = this.advised.getTargetClass();

            List<?> chain = this.advised
                    .getInterceptorsAndDynamicInterceptionAdvice(method,
                            targetClass);
            boolean haveAdvice = !chain.isEmpty();
            boolean exposeProxy = this.advised.isExposeProxy();
            boolean isStatic = this.advised.getTargetSource().isStatic();
            boolean isFrozen = this.advised.isFrozen();
            if ((haveAdvice) || (!isFrozen)) {
                if (exposeProxy) {
                    if (CglibAopProxy.logger.isDebugEnabled()) {
                        CglibAopProxy.logger
                                .debug("Must expose proxy on advised method: "
                                        + method);
                    }
                    return 0;
                }
                String key = method.toString();
                if ((isStatic) && (isFrozen)
                        && (this.fixedInterceptorMap.containsKey(key))) {
                    if (CglibAopProxy.logger.isDebugEnabled()) {
                        CglibAopProxy.logger
                                .debug("Method has advice and optimisations are enabled: "
                                        + method);
                    }
                    int index = ((Integer) this.fixedInterceptorMap.get(key))
                            .intValue();
                    return index + this.fixedInterceptorOffset;
                }
                if (CglibAopProxy.logger.isDebugEnabled()) {
                    CglibAopProxy.logger
                            .debug("Unable to apply any optimisations to advised method: "
                                    + method);
                }
                return 0;
            }
            if ((exposeProxy) || (!isStatic)) {
                return 1;
            }
            Class<?> returnType = method.getReturnType();
            if (targetClass == returnType) {
                if (CglibAopProxy.logger.isDebugEnabled()) {
                    CglibAopProxy.logger
                            .debug("Method "
                                    + method
                                    + "has return type same as target type (may return this) - using INVOKE_TARGET");
                }
                return 1;
            }
            if ((returnType.isPrimitive())
                    || (!returnType.isAssignableFrom(targetClass))) {
                if (CglibAopProxy.logger.isDebugEnabled()) {
                    CglibAopProxy.logger
                            .debug("Method "
                                    + method
                                    + " has return type that ensures this cannot be returned- using DISPATCH_TARGET");
                }
                return 3;
            }
            if (CglibAopProxy.logger.isDebugEnabled()) {
                CglibAopProxy.logger
                        .debug("Method "
                                + method
                                + "has return type that is assignable from the target type (may return this) - "
                                + "using INVOKE_TARGET");
            }
            return 1;
        }

        public boolean equals(Object other) {
            if (other == this) {
                return true;
            }
            if (!(other instanceof ProxyCallbackFilter)) {
                return false;
            }
            ProxyCallbackFilter otherCallbackFilter = (ProxyCallbackFilter) other;
            AdvisedSupport otherAdvised = otherCallbackFilter.advised;
            if ((this.advised == null) || (otherAdvised == null)) {
                return false;
            }
            if (this.advised.isFrozen() != otherAdvised.isFrozen()) {
                return false;
            }
            if (this.advised.isExposeProxy() != otherAdvised.isExposeProxy()) {
                return false;
            }
            if (this.advised.getTargetSource().isStatic() != otherAdvised
                    .getTargetSource().isStatic()) {
                return false;
            }
            if (!AopProxyUtils.equalsProxiedInterfaces(this.advised,
                    otherAdvised)) {
                return false;
            }
            Advisor[] thisAdvisors = this.advised.getAdvisors();
            Advisor[] thatAdvisors = otherAdvised.getAdvisors();
            if (thisAdvisors.length != thatAdvisors.length) {
                return false;
            }
            for (int i = 0; i < thisAdvisors.length; i++) {
                Advisor thisAdvisor = thisAdvisors[i];
                Advisor thatAdvisor = thatAdvisors[i];
                if (!equalsAdviceClasses(thisAdvisor, thatAdvisor)) {
                    return false;
                }
                if (!equalsPointcuts(thisAdvisor, thatAdvisor)) {
                    return false;
                }
            }
            return true;
        }

        private boolean equalsAdviceClasses(Advisor a, Advisor b) {
            Advice aa = a.getAdvice();
            Advice ba = b.getAdvice();
            if ((aa == null) || (ba == null)) {
                return aa == ba;
            }
            return aa.getClass().equals(ba.getClass());
        }

        private boolean equalsPointcuts(Advisor a, Advisor b) {
            if ((a instanceof PointcutAdvisor)) {
                if (!(b instanceof PointcutAdvisor)) {
                    break label42;
                }
            }
            label42: return ObjectUtils.nullSafeEquals(
                    ((PointcutAdvisor) a).getPointcut(),
                    ((PointcutAdvisor) b).getPointcut());
        }

        public int hashCode() {
            int hashCode = 0;
            Advisor[] advisors = this.advised.getAdvisors();
            for (Advisor advisor : advisors) {
                Advice advice = advisor.getAdvice();
                if (advice != null) {
                    hashCode = 13 * hashCode + advice.getClass().hashCode();
                }
            }
            hashCode = 13 * hashCode + (this.advised.isFrozen() ? 1 : 0);
            hashCode = 13 * hashCode + (this.advised.isExposeProxy() ? 1 : 0);
            hashCode = 13 * hashCode + (this.advised.isOptimize() ? 1 : 0);
            hashCode = 13 * hashCode + (this.advised.isOpaque() ? 1 : 0);
            return hashCode;
        }
    }
}

代理模式在Struts2中的实际应用

Struts2中的拦截器,其实就是代理模式的一种实现。Struts2是一个基于Sun J2EE的MVC框架,它只有一个中心控制器,采用XML定制转向的URL,采用Action来处理逻辑。
这里写图片描述

在Struts2中,一个重要的类是org.apache.struts2.dispatcher.FilterDispatcher,用户通过浏览器提交一个HttpServletRequest请求后,请求被在web.xml中定义的过滤器FilterDispatcher拦截,在FilterDispatcher过滤器中首先询问ActionMapper是否需要调用某个Action来处理请求,如果ActionMapper决定调用某个某个Action,FilterDispatcher则把请求的处理交给ActionProxy,ActionProxy通过配置文件struts.xml找到需要调用的Action类,然后ActionProxy创建一个ActionInvocation实例并调用该Action,但在调用之前,ActionInvocation会根据加载Action相关的所有Interceptor,等Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回Result。

在Struts2中,拦截器其实是AOP的一种实现方式,通过拦截器可以在Action执行的前后处理一些相应的操作。

ActionProxy

package com.opensymphony.xwork2;

import com.opensymphony.xwork2.config.entities.ActionConfig;

public abstract interface ActionProxy {
    //插入Action实例
    public abstract Object getAction();

    //获取Action名称
    public abstract String getActionName();

    //获取Action配置
    public abstract ActionConfig getConfig();

    public abstract void setExecuteResult(boolean paramBoolean);

    public abstract boolean getExecuteResult();

    //代理方法
    public abstract ActionInvocation getInvocation();

    public abstract String getNamespace();

    public abstract String execute() throws Exception;

    public abstract String getMethod();

    public abstract boolean isMethodSpecified();
}

DefaultActionProxy

package com.opensymphony.xwork2;

import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.RuntimeConfiguration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
import java.io.Serializable;
import java.util.Locale;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;

public class DefaultActionProxy implements ActionProxy, Serializable {
    private static final long serialVersionUID = 3293074152487468527L;
    private static final Logger LOG = LoggerFactory
            .getLogger(DefaultActionProxy.class);
    protected Configuration configuration;
    protected ActionConfig config;
    protected ActionInvocation invocation;
    protected UnknownHandlerManager unknownHandlerManager;
    protected String actionName;
    protected String namespace;
    protected String method;
    protected boolean executeResult;
    protected boolean cleanupContext;
    protected ObjectFactory objectFactory;
    protected ActionEventListener actionEventListener; // 定义监听事件
    private boolean methodSpecified = true;

    // 初始化构造函数,下列代码用于实现代理的默认构造函数
    protected DefaultActionProxy(ActionInvocation inv, String namespace,
            String actionName, String methodName, boolean executeResult,
            boolean cleanupContext) {
        this.invocation = inv;
        this.cleanupContext = cleanupContext;
        if (LOG.isDebugEnabled()) {
            LOG.debug("Creating an DefaultActionProxy for namespace "
                    + namespace + " and action name " + actionName,
                    new String[0]);
        }
        this.actionName = StringEscapeUtils.escapeHtml4(actionName);
        this.namespace = namespace;
        this.executeResult = executeResult;
        this.method = StringEscapeUtils.escapeEcmaScript(StringEscapeUtils
                .escapeHtml4(methodName));
    }

    @Inject
    public void setObjectFactory(ObjectFactory factory) {
        this.objectFactory = factory;
    }

    @Inject
    public void setConfiguration(Configuration config) {
        this.configuration = config;
    }

    @Inject
    public void setUnknownHandler(UnknownHandlerManager unknownHandlerManager) {
        this.unknownHandlerManager = unknownHandlerManager;
    }

    @Inject(required = false)
    public void setActionEventListener(ActionEventListener listener) {
        this.actionEventListener = listener;
    }

    public Object getAction() {
        return this.invocation.getAction();
    }

    public String getActionName() {
        return this.actionName;
    }

    public ActionConfig getConfig() {
        return this.config;
    }

    public void setExecuteResult(boolean executeResult) {
        this.executeResult = executeResult;
    }

    public boolean getExecuteResult() {
        return this.executeResult;
    }

    public ActionInvocation getInvocation() {
        return this.invocation;
    }

    public String getNamespace() {
        return this.namespace;
    }

    //通过代理要执行的方法
    public String execute() throws Exception {
        ActionContext nestedContext = ActionContext.getContext();
        ActionContext.setContext(this.invocation.getInvocationContext());

        String retCode = null;

        String profileKey = "execute: ";
        try {
            UtilTimerStack.push(profileKey);

            retCode = this.invocation.invoke();
        } finally {
            if (this.cleanupContext) {
                ActionContext.setContext(nestedContext);
            }
            UtilTimerStack.pop(profileKey);
        }
        return retCode;
    }

    public String getMethod() {
        return this.method;
    }

    //指定方法
    private void resolveMethod() {
        if (StringUtils.isEmpty(this.method)) {
            this.method = this.config.getMethodName();
            if (StringUtils.isEmpty(this.method)) {
                this.method = "execute";
            }
            this.methodSpecified = false;
        }
    }

    //在方法执行前要执行的方法,在代理类执行前要执行的内容
    protected void prepare() {
        String profileKey = "create DefaultActionProxy: ";
        try {
            UtilTimerStack.push(profileKey);
            this.config = this.configuration.getRuntimeConfiguration()
                    .getActionConfig(this.namespace, this.actionName);
            if ((this.config == null)
                    && (this.unknownHandlerManager.hasUnknownHandlers())) {
                this.config = this.unknownHandlerManager.handleUnknownAction(
                        this.namespace, this.actionName);
            }
            if (this.config == null) {
                throw new ConfigurationException(getErrorMessage());
            }
            resolveMethod();
            if (!this.config.isAllowedMethod(this.method)) {
                throw new ConfigurationException("Invalid method: "
                        + this.method + " for action " + this.actionName);
            }
            this.invocation.init(this);
        } finally {
            UtilTimerStack.pop(profileKey);
        }
    }

    //获取错误信息
    protected String getErrorMessage() {
        if ((this.namespace != null) && (this.namespace.trim().length() > 0)) {
            return LocalizedTextUtil.findDefaultText(
                    "xwork.exception.missing-package-action",
                    Locale.getDefault(), new String[] { this.namespace,
                            this.actionName });
        }
        return LocalizedTextUtil.findDefaultText(
                "xwork.exception.missing-action", Locale.getDefault(),
                new String[] { this.actionName });
    }

    public boolean isMethodSpecified() {
        return this.methodSpecified;
    }
}

StrutsActionProxy

package org.apache.struts2.impl;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.DefaultActionProxy;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;

public class StrutsActionProxy extends DefaultActionProxy {
    private static final long serialVersionUID = -2434901249671934080L;

    public StrutsActionProxy(ActionInvocation inv, String namespace,
            String actionName, String methodName, boolean executeResult,
            boolean cleanupContext) {
        super(inv, namespace, actionName, methodName, executeResult,
                cleanupContext);
    }

    //执行要代理的方法
    public String execute() throws Exception {
        ActionContext previous = ActionContext.getContext();
        ActionContext.setContext(this.invocation.getInvocationContext());
        try {
            return this.invocation.invoke();
        } finally {
            if (this.cleanupContext) {
                ActionContext.setContext(previous);
            }
        }
    }

    protected void prepare() {
        super.prepare();
    }

    protected String getErrorMessage() {
        if ((this.namespace != null) && (this.namespace.trim().length() > 0)) {
            String contextPath = ServletActionContext.getRequest()
                    .getContextPath();
            return LocalizedTextUtil.findDefaultText(
                    "struts.exception.missing-package-action.with-context",
                    Locale.getDefault(), new String[] { this.namespace,
                            this.actionName, contextPath });
        }
        return super.getErrorMessage();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值