在第一篇中的例子和概念介绍中我们对 Advice 有了一个初步的认知。在 Spring AOP 中,Advice 的作用就是用来描述 Spring AOP 围绕方法调用而注入的切面行为。本篇文章将从源码的角度来看一看 Advice 到底是什么样的?又是怎么完成通知的?
Advice 接口
1 2 3 4 5 6 7 8 9 10 11
package org.aopalliance.aop;
/** * Tag interface for Advice. Implementations can be any type * of advice, such as Interceptors. * @author Rod Johnson * @version $Id: Advice.java,v 1.1 2004/03/19 17:02:16 johnsonr Exp $ */ publicinterfaceAdvice {
/** * Invoke the advice method. * @param jpMatch the JoinPointMatch that matched this execution join point * @param returnValue the return value from the method execution (may be null) * @param ex the exception thrown by the method execution (may be null) * @return the invocation result * @throws Throwable in case of invocation failure */ protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex)throws Throwable { return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex)); }
/** * Return a proxy. Invoked when clients obtain beans from this factory bean. * Create an instance of the AOP proxy to be returned by this factory. * The instance will be cached for a singleton, and create on each call to * {@code getObject()} for a proxy. * @return a fresh AOP proxy reflecting the current state of this factory */ @Override public Object getObject()throws BeansException { //初始化Advisor链 initializeAdvisorChain(); //如果是单例,则获取单例对象 if (isSingleton()) { return getSingletonInstance(); } else { if (this.targetName == null) { logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " + "Enable prototype proxies by setting the 'targetName' property."); } return newPrototypeInstance(); } }
/** * Return the singleton instance of this class's proxy object, * lazily creating it if it hasn't been created already. * @return the shared singleton proxy */ privatesynchronized 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) { thrownewFactoryBeanNotInitializedException("Cannot determine target class for proxy"); } setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } // Initialize the shared singleton instance. super.setFrozen(this.freezeProxy); this.singletonInstance = getProxy(createAopProxy()); } returnthis.singletonInstance; }