深入浅出设计模式(七):9.代理模式
2016-01-15 15:35
543 查看
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) 1b024 { 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(); } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序