Spring AOP的实现与设计

1、代理对象是怎么生成的

ProxyFactoryBean是SpringAOP实现的核心,先经过代码使用ProxyFactoryBean完成一次AOP调用java

public class App {
    public static void main(String[] args) {

        //1.建立ProxyFactoryBean,用以建立指定对象的Proxy对象
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();

        proxyFactoryBean.setInterfaces(TicketService.class);
        proxyFactoryBean.setTarget(new RailwayStation());
        proxyFactoryBean.setProxyTargetClass(true);

        //2.添加Advice拦截器
        proxyFactoryBean.addAdvice(new TicketServiceAfterReturningAdvice());
        proxyFactoryBean.addAdvice(new TicketServiceAroundAdvice());
        proxyFactoryBean.addAdvice(new TicketServiceBeforeAdvice());
        proxyFactoryBean.addAdvice(new TicketServiceThrowsAdvice());

        //3.获取代理对象
        TicketService ticketService = (TicketService)proxyFactoryBean.getObject();
        ticketService.sellTicket();
    }
}

public class RailwayStation implements TicketService {
    @Override
    public void sellTicket() {
        System.out.println("售票............");
    }

    @Override
    public void inquire() {
        System.out.println("查询............");
    }

    @Override
    public void withdraw() {
        System.out.println("退票............");
    }
}

public interface TicketService {
    //售票
    void sellTicket();

    //问询
    void inquire();

    //退票
    void withdraw();
}

分别建立Before、AfterReturn、Around、Throw四个Advice数据结构

public class TicketServiceAfterReturningAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("AFTER_RETURNING:本次服务已结束....");
    }
}

public class TicketServiceAroundAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("AROUND_ADVICE:BEGIN....");
        Object returnValue = invocation.proceed();
        System.out.println("AROUND_ADVICE:END.....");
        return returnValue;
    }
}

public class TicketServiceBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("BEFORE_ADVICE: 欢迎光临代售点....");
    }
}

public class TicketServiceThrowsAdvice implements ThrowsAdvice {
    public void afterThrowing(Exception ex) {
        System.out.println("AFTER_THROWING....");
    }

    public void afterThrowing(Method method, Object[] args, Object target, Exception ex) {
        System.out.println("afterThrowing调用过程出错啦!!!!!");

    }
}

运行结果以下:ide

使用过程当中主要围绕ProxyFactoryBean,从类图中发现它继承了AdvisedSupport,AdvisedSupport数据结构以下:ui

  • List<Advisor> advisors:Advice集合,若是执行 proxyFactoryBean.addAdvice(afterReturningAdvice); afterReturningAdvice会被包装成Advisor添加进来。
  • List<Class<?>> interfaces:代理集合,代理对象须要实现的接口,对应proxyFactoryBean.setInterfaces(TicketService.class)
  • TargetSource targetSource:对TargetClass对象的封装,对应 proxyFactoryBean.setTarget(railwayStation)

经过ProxyFactoryBean配置完接口、真正被调用目标、Advice以后,使用proxyFactoryBean.getObject()生成代理对象,关键步骤是getProxy(createAopProxy())this

【ProxyFactoryBean】
private synchronized Object getSingletonInstance() {
		if (this.singletonInstance == null) {
			this.targetSource = freshTargetSource();
			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
				// Rely on AOP infrastructure to tell us what interfaces to proxy.
				Class<?> targetClass = getTargetClass();
				if (targetClass == null) {
					throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
				}
				setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
			}
			// Initialize the shared singleton instance.
			super.setFrozen(this.freezeProxy);
            //建立CglibProxy 或 JdkProxy
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}

createAopProxy()具体作了什么呢,主要涉及到DefaultAopProxyFactory 、ObjenesisCglibAopProxy、JdkDynamicAopProxy、AopProxyFactory结合工厂+单例模式完成。spa

获取到具体的AopProxy以后,再经过aopProxy.getProxy执行准备工做,例如把Advice转换成MethodInterceptor等。3d

2、Advice链(即拦截器链)的构造过程以及执行机制

JdkDynamicAopProxy 和CglibAopProxy只是建立代理方式的两种方式而已,实际上咱们为方法调用添加的各类Advice的执行逻辑都是统一的。在Spring的底层,会把咱们定义的各个Adivce分别包裹成一个 MethodInterceptor,这些Advice按照加入Advised顺序,构成一个AdivseChain。代理

例如示例代码中添加四个Advice,在CglibProxy中分别使用AfterReturningAdviceAdapter、MethodBeforeAdviceAdapter、ThrowsAdviceAdapter.getInterceptor(Advisor advisor)包装成新的MethodInterceptor。因为TicketServiceAroundAdvice继承了MethodInterceptor,因此不用适配。例如ThrowsAdviceAdaptercode

class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof ThrowsAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		return new ThrowsAdviceInterceptor(advisor.getAdvice());
	}

}

再看看每一个拦截器作了什么。对象

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
 
	private MethodBeforeAdvice advice;
 
	/**
	 * Create a new MethodBeforeAdviceInterceptor for the given advice.
	 * @param advice the MethodBeforeAdvice to wrap
	 */
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}
 
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		//在调用方法以前,先执行BeforeAdvice
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		return mi.proceed();
	}
}

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
	private final AfterReturningAdvice advice;
 
	/**
	 * Create a new AfterReturningAdviceInterceptor for the given advice.
	 * @param advice the AfterReturningAdvice to wrap
	 */
	public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}
 
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		//先调用invocation
		Object retVal = mi.proceed();
		//调用成功后,调用AfterReturningAdvice
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}
}
public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
 
	private static final String AFTER_THROWING = "afterThrowing";
 
	private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);
 
	private final Object throwsAdvice; 

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		//使用大的try,先执行代码,捕获异常
		try {
			return mi.proceed();
		}
		catch (Throwable ex) {
			//获取异常处理方法
			Method handlerMethod = getExceptionHandler(ex);
			//调用异常处理方法
			if (handlerMethod != null) {
				invokeHandlerMethod(mi, ex, handlerMethod);
			}
			throw ex;
		}
	}
 
	private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
		Object[] handlerArgs;
		if (method.getParameterTypes().length == 1) {
			handlerArgs = new Object[] { ex };
		}
		else {
			handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
		}
		try {
			method.invoke(this.throwsAdvice, handlerArgs);
		}
		catch (InvocationTargetException targetEx) {
			throw targetEx.getTargetException();
		}
	}
 
}

每一个拦截器会在不一样时刻执行本身的拦截逻辑,依据上图的拦截器顺序(After——Around——Before——Throw),图示说明调用关系。

3、pointcut是如何工做的

若是只想拦截某个方法,能够手动建立PointcutAdvisor

//手动建立一个pointcut,专门拦截inquire方法
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution( * inquire(..))");
proxyFactoryBean.addAdvisor(new FilteredAdvisor(pointcut,beforeAdvice));

private static class FilteredAdvisor implements PointcutAdvisor {
        private Pointcut pointcut;
        private Advice advice;

        public FilteredAdvisor(Pointcut pointcut, Advice advice) {
            this.pointcut = pointcut;
            this.advice = advice;
        }

        @Override
        public Pointcut getPointcut() {
            return pointcut;
        }

        @Override
        public Advice getAdvice() {
            return advice;
        }

        @Override
        public boolean isPerInstance() {
            return false;
        }
    }

Spring处理该PointcutAdvisor是在DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice方法中

首先会获取FilterAdvisor里PointCut的MethodMatcher,这里包含"execution( * inquire(..))"表达式,和入参里的method比较是否一致,因为TicketService有sellTicket、inquire、withdraw,因此MethodMatcher会比较三次,只有inquire能经过,组装成一个InterceptorAndDynamicMethodMatcher,交给ReflectiveMethodInvocation。因此只有执行inquire方法会出现before拦截,其余方法正常执行。

相关文章
相关标签/搜索