1.Spring AOP的底层实现常用类:
分析Spring AOP的底层实现首先要从ProxyConfig类开始,ProxyConfig是所有产生Spring AOP代理对象的基类,它是一个数据类,主要为其AOP代理对象工厂实现类提供配置属性。根据ProxyConfig的继承体系分析创建AOP代理常用类的作用:
(1).AdvisedSupport是ProxyConfig的子类,它封装了AOP中对通知(Advice)和通知器(Advisor)的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象的创建,AdvisedSupport把它交给子类去实现。
(2).ProxyCreatorSupport是AdvisedSupport的子类,它是其子类创建AOP代理对象的一个辅助类,提供不同AOP代理对象生成的通用操作,具体的AOP代理对象生成,由ProxyCreatorSupport的子类完成。
(3).创建AOP代理对象的类:
ProxyCreatorSupport有3个子类,分别创建不同的AOP代理对象,具体如下:
a.AspectJProxyFactory:主要用于创建AspectJ的AOP应用,起到集成Spring和AspectJ的作用。
b.ProxyFactory:创建编程式的Spring AOP应用。
c.ProxyFactoryBean:创建声明式的Spring AOP应用。
2.声明式Spring AOP代理工厂对象ProxyFactoryBean:
我们以ProxyFactoryBean为例,分析Spring AOP的实现原理,ProxyFactoryBean是Spring中一个非常灵活的创建AOP应用的底层方法,封装了AOP的主要功能。
一个简单的AOP代理工厂对象的配置如下:
3.ProxyFactoryBean生成AOPProxy代理对象:
从2中ProxyFactoryBean的简单配置例子我们可以看出,ProxyFactoryBean是用来配置目标对象和切面行为Advice的,ProxyFactoryBean通过其配置的拦截器名称interceptorNames即通知器Advisor将切面行为Advice应用到目标对象中。
在ProxyFactoryBean中,需要为待增强目标对象目标对象生成Proxy代理对象,从而为AOP切面的编织提供基础,下面通过源码分析ProxyFactoryBean的生成AOPProxy代理对象的实现过程:
(1).ProxyFactoryBean产生代理对象的主要源码:
public class ProxyFactoryBean extends ProxyCreatorSupport implements FactoryBean
通过源码分析,我们了解到AOPProxyFactory实现了FactoryBean接口,所以本身也是一个Spring的工厂Bean,AOP代理工厂的主要功能概况为:
a.初始化通知器链,将配置的通知器链添加到容器存放通知/通知器的集合中。
b.根据单态模式/原型模式,获取AOPProxy产生AOPProxy代理对象。
(2).AOP创建辅助器(AOPCreatorSupport)获取AOPProxy代理对象:
AOPProxyFactory的getSingletonInstance和newPrototypeInstance方法均通过调用AOPCreatorSupport的createAopProxy()方法获取AOPProxy,主要源码如下:
public class ProxyCreatorSupport extends AdvisedSupport { //AOPProxy工厂 private AopProxyFactory aopProxyFactory; //当第一个AOPProxy代理对象被创建时,设置为true private boolean active = false; public AopProxyFactory getAopProxyFactory() { return this.aopProxyFactory; } //默认使用DefaultAopProxyFactory作用AOP代理工厂 public ProxyCreatorSupport() { this.aopProxyFactory = new DefaultAopProxyFactory(); } //创建AOPProxy代理的入口方法 protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } //调用DefaultAopProxyFactory的创建AOPProxy代理的方法 return getAopProxyFactory().createAopProxy(this); } //激活AOP代理配置,向容器注册代理回调监听器,第一次创建AOP代理时调用 private void activate() { this.active = true; for (AdvisedSupportListener listener : this.listeners) { listener.activated(this); } } …… }
通过对ProxyCreatorSupport的源码分析,我们知道真正创建AOPProxy代理对象的是DefaultAopProxyFactory类。
(3).DefaultAopProxyFactory创建AOPProxy代理对象:
DefaultAopProxyFactory是AOP创建辅助器(AOPCreatorSupport)默认的AOP代理工厂,DefaultAopProxyFactory的createAopProxy方法实现了创建AOP代理的功能,源码如下:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { //判断CGLIB类库是否在classpath中 private static final boolean cglibAvailable = ClassUtils.isPresent("net.sf.cglib.proxy.Enhancer", DefaultAopProxyFactory.class.getClassLoader()); //创建AOP代理对象 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //如果AOP使用显式优化,或者配置了目标类,或者只使用Spring支持的代理接口 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { //获取AOP配置的目标类 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."); } //如果配置的AOP目标类是接口,则使用JDK动态代理机制来生成AOP代理 if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } //如果AOP配置的目标类不是接口,则使用CGLIB的方式来生成AOP代理 if (!cglibAvailable) { throw new AopConfigException( "Cannot proxy target class because CGLIB2 is not available. " + "Add CGLIB to the class path or specify proxy interfaces."); } return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } } //判断AOP是否只配置了SpringProxy代理接口或者没有配置任何代理接口 private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) { //获取AOP配置的所有AOP代理接口 Class[] interfaces = config.getProxiedInterfaces(); return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.equals(interfaces[0]))); } }
通过对DefaultAopProxyFactory的源码分析,我们了解了Spring在创建AOP代理对象时,如果配置的目标类是接口,则使用JDK的动态代理机制来生成AOP代理,如果使用的不是接口,则使用CGLIB方式来生成AOP的动态代理。
4.JDK动态代理机制创建AOPProxy代理对象:
JDK的动态代理机制只能对接口起作用,即如果要对一个对象使用JDK动态代理方式生成代理对象时,该对象必须实现接口,Spring中通过JdkDynamicAopProxy类使用JDK动态代理机制生成AOPProxy代理对象,JdkDynamicAopProxy的主要源码如下:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { …… //JdkDynamicAopProxy的构造方法 public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); //获取AOPBeanFactory中配置的通知器链和目标源 if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); } //为当前对象设置AOP配置 this.advised = config; } //获取AOP代理对象的入口方法 public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } //创建AOP代理对象 public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } //获取AOPBeanFactory中配置的代理接口 Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); //查找代理目标的接口中是否定义equals()和hashCode()方法 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); //使用JDK的动态代理机制创建AOP代理对象 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } //查找给定类或接口中是否定义了equals()和hashCode()方法 private void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces) { //遍历给定的类/接口数组 for (Class proxiedInterface : proxiedInterfaces) { //或者给定类/接口中所有声明的方法 Method[] methods = proxiedInterface.getDeclaredMethods(); //遍历类/接口中的声明的方法 for (Method method : methods) { //如果方法是equals()方法,则设置当前对象equalsDefined属性 if (AopUtils.isEqualsMethod(method)) { this.equalsDefined = true; } //如果方法是hashCode()方法,则设置当前对象hashCodeDefined属性 if (AopUtils.isHashCodeMethod(method)) { this.hashCodeDefined = true; } if (this.equalsDefined && this.hashCodeDefined) { return; } } } } //AOP代理对象的回调方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; //获取通知的目标源 TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { //如果代理目标对象的接口中没有定义equals()方法,且当前调用的方法 //是equals()方法,即目标对象没有自己实现equals()方法 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0]); } //如果代理目标对象的接口中没有定义hashCode()方法,且当前调用的方法 //是hashCode()方法,即目标对象没有自己实现hashCode()方法 if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return hashCode(); } //如果AOP配置了通知,使用反射机制调用通知的同名方法 if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; //如果当前通知暴露了代理,则将当前代理使用currentProxy()方法变为可用代理 if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //获取目标对象 target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } //获取目标对象方法配置的拦截器(通知器)链 List
通过上述源码分析,我们看到JdkDynamicAopProxy本身实现了InvocationHandler接口和invoke()方法,JDK的动态代理机制的工作原理是:当调用目标对象的方法时,不是直接调用目标对象,而是首先生成一个目标对象的动态代理对象,触发代理对象的invoke()方法,代理的invoke()方法才会真正调用目标对象的方法。Spring AOP的实现原理是在代理对象invoke()方法调用目标对象的方法时,调用配置的通知。
5.CglibProxyFactory创建AOPProxy代理:
JDK的动态代理只能针对接口生成代理对象,对于没有实现接口的目标对象,必须通过第3方的CGLIB来生成代理对象,CglibProxyFactory创建AOPProxy代理的主要源码如下:
//通过CGLIB方式创建AOP代理对象 public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource()); } try { //从代理创建辅助类中获取在IoC容器中配置的目标对象 Class rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); //将目标对象本身做为自己的基类 Class proxySuperClass = rootClass; //检查获取到的目标类是否是CGLIB产生的 if (AopUtils.isCglibProxyClass(rootClass)) { //如果目标类是有CGLIB产生的,获取目标类的基类 proxySuperClass = rootClass.getSuperclass(); //获取目标类的接口 Class[] additionalInterfaces = rootClass.getInterfaces(); //将目标类的接口添加到容器AOP代理创建辅助类的配置中 for (Class additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } //校验代理基类 validateClassIfNecessary(proxySuperClass); //配置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的基类 enhancer.setSuperclass(proxySuperClass); enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class)); //设置enhancer的接口 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setInterceptDuringConstruction(false); //设置enhancer的回调方法 Callback[] callbacks = getCallbacks(rootClass); enhancer.setCallbacks(callbacks); //将通知器中配置作为enhancer的方法过滤 enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); Class[] types = new Class[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } //设置enhancer的回调类型 enhancer.setCallbackTypes(types); //创建代理对象 Object proxy; if (this.constructorArgs != null) { proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs); } else { proxy = enhancer.create(); } return proxy; } catch (CodeGenerationException 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 (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 (Exception ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); } } //获取给定类的回调通知 private Callback[] getCallbacks(Class rootClass) throws Exception { //优化参数 boolean exposeProxy = this.advised.isExposeProxy(); boolean isFrozen = this.advised.isFrozen(); boolean isStatic = this.advised.getTargetSource().isStatic(); //根据AOP配置创建一个动态通知拦截器,CGLIB创建的动态代理会自动调用 //DynamicAdvisedInterceptor类的intercept方法对目标对象进行拦截处理 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); Callback targetInterceptor; //根据是否暴露代理,创建直接应用目标的通知 if (exposeProxy) { targetInterceptor = isStatic ? new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); } else { targetInterceptor = isStatic ? new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedInterceptor(this.advised.getTargetSource()); } // 创建目标分发器 Callback targetDispatcher = isStatic ? new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp(); Callback[] mainCallbacks = new Callback[]{ aopInterceptor, //普通通知 targetInterceptor, // 如果优化则不考虑配置的通知 new SerializableNoOp(), //没有被覆盖的方法 targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised) }; Callback[] callbacks; //如果目标是静态的,并且通知链被冻结,则使用优化AOP调用,直接对方法使用 //固定的通知链 if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap
通过上面对CGLIB创建代理和获取回答通知的源码分析,我们了解到CGLIB在获取代理的通知时,会创建DynamicAdvisedInterceptor类,当应用调用目标对象的方法时,不是直接调用目标对象,而是通过CGLIB创建的代理对象来调用目标对象,在调用目标对象的方法时,触发DynamicAdvisedInterceptor的intercept回调方法对目标对象进行处理,CGLIB回调拦截器链的源码如下:
//CGLIB回调AOP拦截器链 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; Class targetClass = null; Object target = null; try { //如果通知器暴露了代理 if (this.advised.exposeProxy) { //设置给定的代理对象为要被拦截的代理 oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //获取目标对象 target = getTarget(); if (target != null) { targetClass = target.getClass(); } //获取AOP配置的通知 List
6.目标对象方法的调用:
通过上面4和5分别对JdkDynamicAopProxy和Cglib2AopProxy创建AOPProxy代理对象,以及对目标对象的通知器回调我们可以看出,当目标对象没有配置通知器时,代理对象直接调用目标对象的方法,下面具体分析直接调用目标对象方法的过程:
(1).JdkDynamicAopProxy直接调用目标对象方法:
JdkDynamicAopProxy中是通过AopUtils.invokeJoinpointUsingReflection方法来直接调用目标对象的方法,源码如下:
//通过反射机制直接调用目标对象方法 public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable { try { //通过反射使给定的方法可以访问,主要是对protected和private方法使用,//取消严格访问控制权限的限制 ReflectionUtils.makeAccessible(method); //使用反射机制调用目标对象的方法 return method.invoke(target, args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } catch (IllegalArgumentException ex) { throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex); } catch (IllegalAccessException ex) { throw new AopInvocationException("Could not access method [" + method + "]", ex); } }
(2).Cglib2AopProxy直接调用目标对象方法:
Cglib2AopProxy是通过methodProxy.invoke来直接调用目标对象的方法,主要源码如下:
retVal = methodProxy.invoke(target, args);
methodProxy是CGLIB中MethodProxy类的对象,因为我对CGLIB也不熟悉,这里不做深入了解。
7.AOP拦截器链的调用:
通过上面4和5分别对JdkDynamicAopProxy和Cglib2AopProxy创建AOPProxy代理对象,以及对目标对象的通知器回调我们了解到,当目标对象配置了通知器时,在对目标对象方法调用前首先需要回调通知器链,JdkDynamicAopProxy和Cglib2AopProxy都是通过将目标对象方法、方法参数、和通知器链、代理对象等封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链,proceed方法源码如下:
//通用通知器链 public Object proceed() throws Throwable { //如果拦截器链中通知已经调用完毕 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { //这个方法调用AopUtils.invokeJoinpointUsingReflection方法, //通过反射机制直接调用目标对象方法 return invokeJoinpoint(); } //获取拦截器链中的通知器或通知 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //如果获取的通知器或通知是动态匹配方法拦截器类型 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { //动态匹配方法拦截器 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { //如果匹配,调用拦截器的方法 return dm.interceptor.invoke(this); } else { //如果不匹配,递归调用proceed()方法,知道拦截器链被全部调用为止 return proceed(); } } else { //如果不是动态匹配方法拦截器,则切入点在构造对象之前进行静态匹配,调用 //拦截器的方法 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }