您的位置:首页 > 编程语言 > Java开发

深入浅出设计模式(七):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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息