深入理解 Spring 之 源码剖析 AOP(XML 配置方式)

本贴最后更新于 2541 天前,其中的信息可能已经事过境迁

Spring 的两大核心,一是 IOC,我们之前已经学习过,并且已经自己动手实现了一个,而令一个则是大名鼎鼎的 AOP,AOP 的具体概念我就不介绍了,我们今天重点是要从源码层面去看看 spring 的 AOP 是如何实现的。注意,今天楼主给大家分享的是 XML 配置 AOP 的方式,不是我们经常使用的注解方式,为什么呢?

有几个原因:

  1. Spring AOP 在 2.0 版本之前都是使用的 XML 配置方式,封装的层次相比注解要少,对于我们学习 AOP 是个很好的例子。
  2. 虽然现在是 2017 年,现在使用 SpringBoot 都是使用注解了, 但是底层原理都是一样的,只不过多了几层封装。当然,我们也是要去扒开它的源码的。但不是今天。
  3. 楼主也还没有分析注解方式的 AOP。-_-|||

我们主要分为几个步骤去理解:

  1. 查看源码了解 spring AOP 的接口设计。Advice,PointCut,Advisor。
  2. 用一个最简单的代码例子 debug 追踪源码。

那么我们现看第一步:

1. Spring AOP 接口设计

1.1 PointCut (连接点,定义匹配哪些方法)

我们打开 Spring 的源码,查看 PointCut 接口设计:

public interface Pointcut {
	ClassFilter getClassFilter();
	MethodMatcher getMethodMatcher();
	Pointcut TRUE = TruePointcut.INSTANCE;
}

该接口定义了 2 个方法,一个成员变量。我们先看第一个方法, ClassFilter getClassFilter() ,该方法返回一个类过滤器,由于一个类可能会被多个代理类代理,于是 Spring 引入了责任链模式,另一个方法则是 MethodMatcher getMethodMatcher() ,表示返回一个方法匹配器,我们知道,AOP 的作用是代理方法,那么,Spirng 怎么知道代理哪些方法呢?必须通过某种方式来匹配方法的名称来决定是否对该方法进行增强,这就是 MethodMatcher 的作用。还有要给默认的 Pointcut 实例,该实例对于任何方法的匹配结果都是返回 true。

我们关注一下 MethodMatcher 接口:

public interface MethodMatcher {
	boolean matches(Method method, @Nullable Class<?> targetClass);
	boolean isRuntime();
	boolean matches(Method method, @Nullable Class<?> targetClass, Object... args);
	MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}

该接口定义了静态方法匹配器和动态方法匹配器。所谓静态方法匹配器,它仅对方法名签名(包括方法名和入参类型及顺序)进行匹配;而动态方法匹配器,会在运行期检查方法入参的值。静态匹配仅会判别一次,而动态匹配因为每次调用方法的入参都可能不一样,所以每次都必须判断。一般情况下,动态匹配不常用。方法匹配器的类型由 isRuntime()返回值决定,返回 false 表示是静态方法匹配器,返回 true 表示是动态方法匹配器。

总的来说, PointCut 和 MethodMatcher 是依赖关系,定义了 AOP 应该匹配什么方法以及如何匹配。

1.2 Advice (通知,定义在链接点做什么)

注意,Advice 接口只是一个标识,什么也没有定义,但是我们常用的几个接口,比如 BeforeAdvice,AfterAdvice,都是继承自它。我们关注一下 AfterAdvice 的子接口 AfterReturningAdvice :

public interface AfterReturningAdvice extends AfterAdvice {
	void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
}

该接口定义了一个方法,afterReturning,参数分别是返回值,目标方法,参数,目标方法类,在目标方法执行之后会回调该方法。那么我们就可以在该方法中执行我们的切面逻辑,BeforeAdvice 也是一样的道理。

1.3 Advisor (通知器,将 Advice 和 PointCut 结合起来)

有了对目标方法的增强接口 Advice 和 如何匹配目标方法接口 PointCut 接口后,那么我们就需要用一个对象将他们结合起来,发挥 AOP 的作用,所以 Spring 设计了 Advisor(通知器),经过我们刚刚的描述,我们应该知道了,这个 Advisor 肯定依赖了 Advice 和 PointCut,我们看看接口设计:

public interface Advisor {

	Advice EMPTY_ADVICE = new Advice() {};

	Advice getAdvice();

	boolean isPerInstance();

}

还有他的子接口:

public interface PointcutAdvisor extends Advisor {

	Pointcut getPointcut();
}

最重要的两个方法,getAdvice,getPointcut。和我们预想的基本一致。

接下来,我们可以停下来思考一下,现在有了这个东西,我们怎么实现面向切面编程;

  1. 首先我们需要告诉 AOP 在哪里进行切面。比如在某个类的方法前后进行切面。
  2. 告诉 AOP 切面之后做什么,也就是说,我们知道了在哪里进行切面,那么我们也该让 spring 知道在切点处做什么。
  3. 我们知道,Spring AOP 的底层实现是动态代理(不管是 JDK 还是 Cglib),那么就需要一个代理对象,那么如何生成呢?

接下来,我们将通过代码的方式,解答这三个疑惑。

2. 从一个简单的 AOP 例子

首先,我们需要实现刚刚我们说的 3 个接口,还有一个目标类,还要一个配置文件。一个一个来。

2.1. Pointcut 接口实现

package test;

import java.lang.reflect.Method;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;

public class TestPointcut implements Pointcut {

	@Override
	public ClassFilter getClassFilter() {
		return ClassFilter.TRUE;
	}

	@Override
	public MethodMatcher getMethodMatcher() {
		return new MethodMatcher() {

			public boolean matches(Method method, Class<?> targetClass, Object[] args) {
				if (method.getName().equals("test")) {
					return true;
				}
				return false;
			}

			public boolean matches(Method method, Class<?> targetClass) {
				if (method.getName().equals("test")) {
					return true;
				}
				return false;
			}

			public boolean isRuntime() {
				return true;
			}
		};
	}

}

我们如何定义匹配?只要方法名称是 test 则对该方法进行增强或者说拦截。

2.2 AfterAdvice 实现

package test;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class TestAfterAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable {
		System.out.println(
				"after " + target.getClass().getSimpleName() + "." + method.getName() + "()");
	}

}

我们在方法执行完毕后打印该方法的名称和该目标类的名称。这就是我们做的简单增强。

2.3 Advisor 通知器的实现

package test;

import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;

/**
 * 通知器
 */
public class TestAdvisor implements PointcutAdvisor {

	/**
	 * 获取通知处理逻辑
	 */
	@Override
	public Advice getAdvice() {
		return new TestAfterAdvice();
	}

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

	/**
	 * 获取切入点
	 */
	@Override
	public Pointcut getPointcut() {
		return new TestPointcut();
	}

}

我们实现了 PointcutAdvisor 接口,返回我们刚才定义的两个类。完成了他们的组合。

2.4 定义目标类 Targe

package test;

public class TestTarget {

	public void test() {
		System.out.println("target.test()");
	}

	public void test2() {
		System.out.println("target.test2()");
	}
}

该目标的实现和简单,就是 2 个方法,分别打印自己的名字。

2.5 定义 XML 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="testAdvisor" class="test.TestAdvisor"></bean>
	<bean id="testTarget" class="test.TestTarget"></bean>
	<bean id="testAOP" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="targetName">
			<value>testTarget</value>
		</property>
		<property name="interceptorNames">
			<list>
				<value>testAdvisor</value>
			</list>
		</property>
	</bean>

</beans>


可以看到,我们定义了 3 个 bean,上面两个是我们刚刚定义的,下面一个我们要好好说说,ProxyFactoryBean 是一个什么东西呢?首先他是一个 FactoryBean,我们在学习 IOC 的时候知道, FactoryBean 是 Spring 留给我们扩展用的,实现该接口的类可以自定类的各种功能。ProxyFactoryBean 当然也实现了自己的很多自定义功能。ProxyFactoryBean 也是 Spring IOC 环境中创建 AOP 应用的底层方法,Spring 正式通过它来实现对 AOP 的封装。这样我们更加接近 Spring 的底层设计。而该类需要注入两个属性一个目标类,一个拦截类,ProxyFactoryBean 会生成一个动态代理类来完成对目标方法的拦截。

2.6 测试类

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class TestAOP {

	public static void main(String[] args) {
		ApplicationContext applicationContext = new FileSystemXmlApplicationContext(
				"spring-context/src/test/java/test/beans.xml");
		TestTarget target = (TestTarget) applicationContext.getBean("testAOP");
		target.test();
		System.out.println("----------------");
		target.test2();
	}

}

我们看看运行结果:

可以看到结果符合我们的预期,因为我们只配置了在 test 名称的方法之后打印该方法的名称和该目标类的名称,而 test2 则没有配置,因此也就没有打印。

那么是怎么实现的呢? 让我们进入源码看个究竟。

3. 深入 AOP 源码实现

首先我们看看我们的测试代码,我们第一句代码是 IOC 初始化,这个我们就不讲了,我们在之前的文章已经分析过,我们重点看第二行代码,我们 debug 到第三行,看看第二行返回的对象是什么?

我们看到,第二行从 IOC 容器中取出的是一个 Cglib 生成的代理对象,也既是继承了我们 TestTarge 类的实例,而不是我们在 XML 中定义的 ProxyFactoryBean 对象,也就是说, FactoryBean 确实能够在 IOC 容器中做一些定制化。那么我们就很好奇,这个代理对象是怎么生成的。我们从第二行代码开始进入。

首先进入抽象类 AbstractApplicationContext 的 getBean 方法,从容器或获取 Bean,再调用 doGetBean 方法,这个方法我们很熟悉,因为再之前的 IOC 过程中,我们看了好多遍了,我们重点看看该方法实现:

	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();// 设置依赖关系
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						getBean(dep);// 递归
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {// 创建bean
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);// 获取实例
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

该方法会进入到第一个 if 块中的 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null) 方法中,而 getObjectForBeanInstance 方法则会先判断缓存是否存在,如果不存在,则进入父类的 getObjectForBeanInstance 方法,我们看看该方法实现:

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

首先判断是否是 Bean 引用类型并且是否是 Factory 类型,很面向不是 Bean 引用类型(Bean 引用类型指的是 IOC 在解析 XML 文件 的时候,会有 ref 属性,而这个 ref 对象还没有实例化,则暂时创建一个 Bean 引用类型的实例,用于在依赖注入的时候判断是否是 Bean 的属性类型,如果是,则从容器中取出,如果不是,则是基本类型,就直接赋值),然后进入下面的 if 判断,很明显会直接跳过。进入下面的 getCachedObjectForFactoryBean(beanName) 方法,从缓存中取出,很明显,第一次肯定返回 null,继续向下,进入 if 块,重点在 object = getObjectFromFactoryBean(factory, beanName, !synthetic) 方法,我们进入该方法查看:

	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
						}
						this.factoryBeanObjectCache.put(beanName, object);
					}
				}
				return object;
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

该方法还是先重缓存中取出,然后进入 doGetObjectFromFactoryBean(factory, beanName) 方法,我们看看该方法:

	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
							factory.getObject(), acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				object = factory.getObject();// 此处调用 ProxyFactoryBean
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

该方法会直接进入 object = factory.getObject() 行,也就是 ProxyFactoryBean 的 getObject 方法,还记得我们说过,Spring 允许我们从写 getObject 方法来实现特定逻辑吗? 我们看看该方法实现:

	public Object getObject() throws BeansException {
		initializeAdvisorChain();// 为代理对象配置Advisor链
		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();
		}
	}

该方法很重要,首先初始化通知器链,然后获取单例,这里返回的就是我们最初看到的 Cglib 代理。这里的初始化过滤器链的重要作用就是将连接起来,基本实现就是循环我们在配置文件中配置的通知器,按照链表的方式连接起来。具体代码各位有兴趣自己去看,今天这个不是重点。首先判断是否是单例,然后我们着重关注下面的方法 getSingletonInstance();

	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);
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}

该方法是同步方法,防止并发错误,因为有共享变量。首先返回一个包装过的目标对象,然后是否含有接口,我们的目标类没有接口,进入 if 块,从目标类中取出所有接口并设置接口。很明显,并没有什么作用,然后向下走,重要的一行是 getProxy(createAopProxy()),先创建 AOP,再获取代理。我们先看 crateAopProxy。

	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

该方法返回一个 AopProxy 类型的实例,我们看看该接口:

public interface AopProxy {
	Object getProxy();
	Object getProxy(@Nullable ClassLoader classLoader);
}

该接口定义了两个重载方法,我们看看它有哪些实现:

这是该接口的继承图,分别是 JdkDynamicAopProxy 动态代理和 CglibAopProxy 代理。而 JdkDynamicAopProxy 实现了 InvocationHandler 接口,如果熟悉 Java 动态代理,应该和熟悉该接口,实现了该接口的类并实现 invoke 方法,再代理类调用的时候,会回调该方法。实现动态代理。

我们继续看 createAopProxy 方法,该方法主要逻辑是创建一个 AOP 工厂,默认工厂是 DefaultAopProxyFactory,该类的 createAopProxy 方法则根据 ProxyFactoryBean 的一些属性来决定创建哪种代理:

	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

只要满足三个条件中的其中一个就,我们看最后一个判断,是否含有接口,没有则返回 ture,也就是说,如果目标类含有接口,则创建 Cglib 代理,否则则是 JDK 代理。最终创建了一个 ObjenesisCglibAopProxy 代理。

我们回到 ProxyFactoryBean 类的 getProxy 方法,当 createAopProxy 返回一个 Cglib 代理的后,则调用 getProxy 方法获取一个代理对象,我们看看该方法实现:

	@Override
	public Object getProxy(@Nullable 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;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | 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 (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

该方法基本上就是使用了 Cglib 的库的一些 API 最后通过字节码生成代理类,比如 Enhancer 增强器,楼主对 ASM 和 Cglib 也不是很熟悉,下次有机会再看详细实现。总之,我们已经知道了 Spring 是如何生成代理对象的,主要的通过 ProxyFactoryBean 来实现。

最后,返回代理类,执行代理类的方法。完成切面编程。

4. 总结

我们通过一个简单的例子 debug spring 源码,了解了通过配置文件方式配置 AOP 的详细过程,其中起最重要作用的还是 ProxyFactoryBean ,在定制化 Bena 的过程中起到了很大的作用,也提醒了我们,如果想在 Spring 的 bean 容器实现一些特别的功能,可以实现 FactoryBean 接口,自定义自己的需要 Bean。还有一点,今天我们学习的例子是通过 XML 方式,而这个方式确实有些古老,虽然不妨碍我们学习 AOP 的精髓,但我们还是希望能够深入了解基于注解的 AOP 的具体实现,也许实现源码相似,但我们还是想知道到底有哪些不同,最起码楼主在刚刚的调试中发现最新的 SpringBoot 的 AOP 不是基于 ProxyFactroyBean 实现的。但不要灰心,原理都是相同的。剩下的就是我们自己去挖掘。

good luck!!!

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    944 引用 • 1459 回帖 • 17 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone

    博主
    请问你是阿里的嘛
    不然怎么懂那么多
    佩服

  • someone

    哈哈,不存在的。