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
經過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
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),圖示說明調用關係。
若是隻想攔截某個方法,能夠手動建立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攔截,其餘方法正常執行。