Spring AOP源码解析
概述
Spring AOP 核心是动态代理技术,以动态代理为基础,设计出一系列AOP的横切实现,如前置通知、返回通知、异常通知等。同时,Spring AOP还提供了一些列的Pointcut来匹配切入点,可以使用现有的切入点来设计横切面,也可以扩展相关Pointcut方法来实现切入需求。本文主要分成两部分,一个是代理对象的生成,一个是拦截器调用逻辑。
实现
代理对象生成过程
代理对象生成以ProxyFactory的设计为核心,相关类继承关系如下图所示:
- ProxyConfig:是一个数据基类,提供相关基础配置
- AdvisedSupport:封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象的创建,AdvisedSupport把它交给它的子类们去完成。
- ProxyCreatorSupport:可以将它看成是其子类创建AOP代理对象的一个辅助类。通过继承以上提到的基类的功能实现,具体的AOP代理对象的生成,根
据不同的需要,分别由ProxyFactoryBean、AspectJProxyFactory和ProxyFactory来完成。
获取代理对象方法:ProxyFactoryBean#getObject
public Object getObject() throws BeansException {
//为Proxy代理对象配置Advisor链
initializeAdvisorChain();
if (isSingleton()) {
//生成singleton代理对象
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
ProxyFactoryBean#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.
//根据AOP框架来判断需要代理的接口
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
//设置代理对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// 使用ProxyFactory生成需要的Proxy
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(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.");
}
//如果目标类是接口 或者代理类,使用JDK来生成Proxy
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//使用cglib进行代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
在AopProxy代理对象的生成过程中,首先要从AdvisedSupport对象中取得配置的目标对象,这个目标对象是实现AOP功能所必需的。一般而言,默认的方式是使用JDK来产生AopProxy代理对象,但是如果遇到配置的目标对象不是接口类的实现,会使用CGLIB来产生AopProxy代理对象,在使用CGLIB来产生AopProxy代理对象时,因为CGLIB是一个第三方的类库,本身不在JDK的基本类库中,所以需要在CLASSPATH路径中进行正确的配置,以便能够加载和使用。在Spring中,使用JDK和CGLIB来生成AopProxy代理对象的工作,是由JdkDynamicAopProxy
和CglibProxyFactory
来完成的。
JdkDynamicAopProxy
生成代理对象:
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
//调用JDK生成Proxy
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
CglibAopProxy#getProxy
生成唯一代理对象
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
//从Advised中获得在IoC容器中配置的对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
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...
//创建并配置CGLIB的Enhancer,这个Enhancer对象是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.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(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 " + 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);
}
}
通过使用AopProxy
对象封装target目标对象之后,ProxyFactoryBean
的getObject
方法得到的对象就不是一个普通的Java对象了,而是一个AopProxy
代理对象。在ProxyFactoryBean中配置的target目标对象,这时已经不会让应用直接调用其方法实现,而是作为AOP实现的一部分。对target目标对象的方法调用会首先被AopProxy代理对象拦截,对于不同的AopProxy
代理对象生成方式,会使用不同的拦截回调人口。例如,对于JDK的AopProxy
代理对象,使用的是InvocationHandler的invoke
回调入口,而对于CGLIB的AopProxy代理对象,使用的是设置好的callback回调,这是由对CGLIB的使用来决定的。在这些callback回调中,对于AOP实现,是通过DynamicAdvisedInterceptor
来完成的,而DynamicAdvisedInterceptor
的回调入口是intercept方法。
至此,AOP代理对象已经生成,接下来分析AOP如何进行拦截。
拦截器实现
JDK代理拦截
在生成代理对象过程中,传入了this InvocationHandler对象,InvocationHandler是反射类接口,其中的invoke方法是作为JDK Proxy代理对象进行拦截的回调入口出现的,在JdkDynamicAopProxy中实现了InvocationHandler接口,也就是说当Proxy对象的代理方法被调用时,JdkDynamicAopProxy的invoke方法作为Proxy对象的回调函数被触发,从而通过invoke的具体实现,来完成对目标对象方法调用的拦截或者说功能增强的工作。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
//如果目标对象没有实现Object类的基本方法:equals
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
// 如果目标对面没有实现Object类的hashCode方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
// 根据代理对象的配置来调用服务
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
//得到目标对象的方法
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
//获得定义好的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
//如果没有设定拦截器,直接调用target的对应方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
//如果有拦截器的设定,那么需要拦截器之后才调用目标对象的相应方法,通过ReflectiveMethodInvocation方法实现
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
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()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
获取拦截器和动态拦截实现,this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//从配置中获取通知器
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
//拦截器链是通过AdvisorAdapterRegistry.来加入的,这个AdvisorAdapterRegistry
//对advice织入起了很大的作用,在后面的分析中会看到
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
在AdvisorAdapterRegistry中,提供了一系列的adapter适配器,正是这些adapter适配器的实现,为Spring AOP的advice:提供编织能力。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
*/
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
//从Advisor通知配置器中获取advice通知
Advice advice = advisor.getAdvice();
//如果通知是MethodInterceptor类型的通知,直接加入interceptors的list中
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//对通知进行适配,使用已经配置好的Adapter:MethodBeforeAdviceAdapter、
//AfterReturningAdviceAdapterThrowsAdviceAdapter.
//然后从对应的adapter中取出封装好AOP编织功能的拦截器
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
查看适配器类结构:
Spring AOP为了实现advice的织入,设计了特定的拦截器对这些功能进行了封装。虽然应用不会直接用到这些拦截器,但却是advice发挥作用必不可少的准
备。接着这条线索,还是以MethodBeforeAdviceInterceptor
为例,看看它是怎样完成advice的封装的,MethodBeforeAdviceInterceptor
完成的是对MethodBeforeAdvice
通知的封装,可以在MethodBeforeAdviceInterceptor
设计的invoke
回调方法中,看到首先触发了advice
的before
回调,然后才是MethodInvocation
的proceed
方法调用。看到这里,就已经和前面在ReflectiveMethodInvocation
的proceed
分析中联系起来了。回忆一下,在AopProxy代理对象触发的ReflectiveMethodInvocation
的proceed
方法中,在取得拦截器以后,启动了对拦截器invoke方法的调用。按照AOP的配置规则,ReflectiveMethodInvocation
触发的拦截器invoke方法,最终会根据不同的advice类型,触发Spring对不同的advicel的拦截器封装,比如对MethodBeforeAdvice
,最终会触发MethodBeforeAdviceInterceptor
的invoke方法。在MethodBeforeAdviceInterceptor
方法中,会先调用advice的before方法,这就是MethodBeforeAdvice
所需要的对目标对象的增强效果:在方法调用之前完成通知增强。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final 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 {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
CGLIB代理拦截
在CglibAopProxy类中,可以看到具体对CGLIB的使用,比如对Enhancer对象的配置,以及通过Enhancer对象生成代理对象的过程。在这个生成代理对象的过程中,需要注意的是对Enhancer对象callback回调的设置,正是这些回调封装了Spring AOP的实现,就像前面介绍的JDK的Proxy对象的invoke回调方法一样。在Enhancer的callback回调设置中,实际上是通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能的,可以在getCallbacks方法实现中看到回调DynamicAdvisedInterceptor的设置,代码按下:
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
........
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//在这里进行拦截调用
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
...
JDK代理和CGLIB主要是代理方式及AOP拦截的入口逻辑不一样,JDK代理是通过InvocationHandler
回调实现AOP功能,CGLIB是通过设置DynamicAdvisedInterceptor
拦截器来完成AOP功能。