Spring AOP解析(2)--AOP的实现原理及源码解析
前言:
上一篇对于AOP的使用做了简单的介绍,本文开始着重对于AOP的实现原理进行解析,AOP的使用主要是通过自定义标签<aop:aspectj-autoproxy>开启,所以就需要通过该标签入手开始探寻AOP的奥秘
一、<aop:aspectj-autoproxy>标签的解析
Spring的标签分为默认的标签和自定义的标签,自定义的标签都需要自定义解析器来对标签进行解析,所以可以先从该标签的解析器入手。全局搜索aspectj-autoproxy,可以发现Spring-Aop包中果然存在一个aspectj-autoproxy的解析器,在AopNamespaceHandler的初始化方法中定义,注册了一个标签解析器AspectJAutoProxyBeanDefinitionParser,源码如下:
1 public class AopNamespaceHandler extends NamespaceHandlerSupport { 2 3 @Override 4 public void init() { 5 // In 2.0 XSD as well as in 2.1 XSD. 6 registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); 7 registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); 8 registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); 9 10 // Only in 2.0 XSD: moved to context namespace as of 2.1 11 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); 12 } 13 14 }
AspectJAutoProxyBeanDefinitionParser主要需要执行parser方法,源码如下:
1 @Override 2 @Nullable 3 public BeanDefinition parse(Element element, ParserContext parserContext) { 4 AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); 5 extendBeanDefinition(element, parserContext); 6 return null; 7 }
其中核心逻辑在线第4行,用于注册AnnotationAwareAutoProxyCreator,首先是创建一个该类的BeanDefintion,然后是解析<aop:aspectj-autoproxy>标签的两个属性proxy-target-class和expose-proxy,最后注册该BeanDefinition,源码如下:
1 public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( 2 ParserContext parserContext, Element sourceElement) { 3 /** 获取org.springframework.aop.config.internalAutoProxyCreator类的BeanDefinition对象*/ 4 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( 5 parserContext.getRegistry(), parserContext.extractSource(sourceElement)); 6 /** 用于解析 proxy-target-class属性 和 expose-proxy属性*/ 7 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); 8 /** 注册AnnotationAutoProxyCreator组件*/ 9 registerComponentIfNecessary(beanDefinition, parserContext); 10 }
目前可以得出结论,AOP的实现功能或者说<aop:aspectj-autoproxy/>标签的功能实现是通过AnnotationAwareAutoProxyCreator来实现的,而上面的步骤都是在创建和注册AnnotationAwareAutoProxyCreator的bean的定义的过程。
二、AnnotationAwareAutoProxyCreator的源码解析
AnnotationAwareAutoProxyCreator类实现了很多的接口,分别实现了Orderd、BeanPostProcessor的子接口、BeanFactoryAware、BeanClassLoaderAware等接口,而既然实现了BeanPostProcessor接口,很显然在bean加载时就会执行BeanPostProcessor的postProcessorBeforeInstantiation方法和postProcessAfterInitialization方法,其中postProcessBeforeInstantiation方法是在bean实例化之前执行,而postProcessAfterInitialization是在bean执行了init方法之后执行,均是在父类AbstarctAutoProxyCreator中实现。
方法postProcessorBeforeInstantiation源码解析:
1 /** 目标对象源bean集合*/ 2 private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); 3 4 /** 提前曝光的代理引用集合*/ 5 private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16); 6 7 /** 代理类型集合*/ 8 private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16); 9 10 /** 增强bean集合,Advice、PointCut、Advisor、AopInfrastructureBean等类的bean会加入该集合*/ 11 private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256); 12 13 @Override 14 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { 15 /** 16 * 1.根据beanClass和beanName获取缓存的key 17 * 如果是工厂bean则key = &beanName 18 * 如果不是工厂bean则key = beanName 19 * */ 20 Object cacheKey = getCacheKey(beanClass, beanName); 21 22 /** 23 * 2.如果targetSourcedBeans中不包含当前bean则进行判断 24 * */ 25 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { 26 if (this.advisedBeans.containsKey(cacheKey)) { 27 return null; 28 } 29 /** 30 * 3.isInfrastructureClass方法是判断当前beanClass是否是AOP增强相关的接口 31 * 判断beanClass是否是Advice、PointCut、Advisor、AopInfrastructureBean等接口的实现类 32 * 如果是则加入到advisedBeans集合中 33 * */ 34 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { 35 this.advisedBeans.put(cacheKey, Boolean.FALSE); 36 return null; 37 } 38 } 39 40 /** 41 * 4.根据beanClass和beanName获取自定义的TargetSource实例,如果存在的话则创建代理,如果不存在则直接跳过 42 * TargetSource实例相当于就是目标对象bean的封装实例 43 * */ 44 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); 45 if (targetSource != null) { 46 if (StringUtils.hasLength(beanName)) { 47 this.targetSourcedBeans.add(beanName); 48 } 49 /** 4.1.获取当前bean所有的增强数组 */ 50 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); 51 /** 4.2.根据增强数组为目标对象创建代理对象 */ 52 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); 53 this.proxyTypes.put(cacheKey, proxy.getClass()); 54 /** 4.3.返回代理bean*/ 55 return proxy; 56 } 57 return null; 58 }
实例化前置方法逻辑不多,主要是判断有没有自定义的TargetSource对象,如果有自定义的则直接获取增强创建代理,如果不是则直接返回null
其中核心步骤之一
方法postProcessAfterInitialization源码解析
1 @Override 2 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { 3 if (bean != null) { 4 Object cacheKey = getCacheKey(bean.getClass(), beanName); 5 if (this.earlyProxyReferences.remove(cacheKey) != bean) { 6 /** 调用wrapIfNecessary方法为当前bean创建代理*/ 7 return wrapIfNecessary(bean, beanName, cacheKey); 8 } 9 } 10 return bean; 11 } 12 13 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { 14 /** 15 * 第一步:判断当前bean是否已经存在targetSourcedBeans集合和advisedBeans中,并且如果是Advise相关bean则加入到advisedBeans集合中 16 * */ 17 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { 18 return bean; 19 } 20 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { 21 return bean; 22 } 23 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { 24 this.advisedBeans.put(cacheKey, Boolean.FALSE); 25 return bean; 26 } 27 28 /** 29 * 第二步:获取当前bean所有的增强数组,也就是Advisor数组 30 * */ 31 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 32 if (specificInterceptors != DO_NOT_PROXY) { 33 this.advisedBeans.put(cacheKey, Boolean.TRUE); 34 /** 35 * 第三步:将目标bean封装成TargetSource对象,然后根据增强数组创建目标对象的代理对象 36 * */ 37 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); 38 this.proxyTypes.put(cacheKey, proxy.getClass()); 39 return proxy; 40 } 41 42 this.advisedBeans.put(cacheKey, Boolean.FALSE); 43 return bean; 44 }
初始化后置方法逻辑和实例化前置方法逻辑基本上差不多,同样是先获取当前bean的所有增强数组,然后将增强数组织入到bean中创建一个代理对象
总结这两个方法可以看出创建代理的流程一共可以分成三步:
第一步:将当前的bean封装成TargetSource对象,如果自定义优先使用自定义的TargetSource;如果没有自定义则使用默认的SingletonTargetSource对象
第二步:获取当前bean需要增强的所有Advisor数组,也就是需要在这个bean上需要织入的增强对象数组
第三步:根据目标对象的封装对象TargetSource对象 和 增强数组Advisor数组 给当前的bean创建一个代理对象
第一步很好理解,实际就是创建一个TargetSource对象,TargetSource对象中持有目标bean的引用,通过TargetSource对象可以访问到目标对象bean
第二步是获取当前bean需要织入的所有增强数组,通过调用getAdvicesAndAdvisorForBean方法实现,而getAdvicesAndAdvisorForBean方法是通过子类AbstractAdvisorAutoProxyCreator类实现,源码如下:
1 /** 2 * 获取当前bean所有的增强 3 * */ 4 @Override 5 @Nullable 6 protected Object[] getAdvicesAndAdvisorsForBean( 7 Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { 8 9 /** 调用findEligibleAdvisors方法获取Advisor列表*/ 10 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); 11 if (advisors.isEmpty()) { 12 return DO_NOT_PROXY; 13 } 14 return advisors.toArray(); 15 }
直接调用了内部的findEligibleAdvisors方法,继续查看源码:
1 /** 查询Advisor列表*/ 2 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { 3 /** 4 * 1、查询所有定义的Advisor列表 5 * 实现逻辑就是从BeanFactory根据Advisor类型查询所有的Advisor实例,一种是实现来Advisor接口的,一种是被@Aspectj注解修饰的转化成Advisor 6 * */ 7 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 8 /** 9 * 2、根据bean来筛选出需要在当前bean上增强的Advisor列表 10 * 11 * */ 12 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 13 extendAdvisors(eligibleAdvisors); 14 if (!eligibleAdvisors.isEmpty()) { 15 /** 3、对所有Advisor进行排序 */ 16 eligibleAdvisors = sortAdvisors(eligibleAdvisors); 17 } 18 return eligibleAdvisors; 19 }
该方法分成了三步,第一步是从BeanFactory中找到所有的Advisor集合,有的是实现了Advisor接口定义的,有的是通过@AspectJ注解定义转化来的;第二步是找出匹配当前bean的所有Advisor;最后一步是对匹配的Advisor列表进行排序
可以发现第一步逻辑应该还比较清楚,就是从容器中找到所有的Advisor,第三步排序也比较好理解,核心是第二步匹配逻辑比较复杂,所以接下来就着重查看Advisor是如何针对bean进行匹配的,方法为findAdvisorsThatCanApply,源码如下:
1 /** 2 * 查询指定beanClass和beanName中需要增强的Advisor列表 3 * */ 4 protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { 5 6 ProxyCreationContext.setCurrentProxiedBeanName(beanName); 7 try { 8 /** 直接调用AopUtils的findAdvisorThatCanApply方法*/ 9 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); 10 } 11 finally { 12 ProxyCreationContext.setCurrentProxiedBeanName(null); 13 } 14 }
直接调用了AopUtils工具类的findAdvisorsThatCanApply方法,源码如下:
1 public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { 2 if (candidateAdvisors.isEmpty()) { 3 return candidateAdvisors; 4 } 5 List<Advisor> eligibleAdvisors = new ArrayList<>(); 6 /** 7 * 1、遍历所有的Advisor, 调用canApply方法判断当前的bean和当前的advisor是否匹配 8 * */ 9 for (Advisor candidate : candidateAdvisors) { 10 /** 11 * 2、首先判断当前增强是否是引介增强,如果是执行canApply方法判断是否匹配 12 * */ 13 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { 14 eligibleAdvisors.add(candidate); 15 } 16 } 17 boolean hasIntroductions = !eligibleAdvisors.isEmpty(); 18 for (Advisor candidate : candidateAdvisors) { 19 if (candidate instanceof IntroductionAdvisor) { 20 // already processed 21 continue; 22 } 23 /** 24 * 3、如果不是引介增强,则执行canApply方法判断是否匹配 25 * */ 26 if (canApply(candidate, clazz, hasIntroductions)) { 27 eligibleAdvisors.add(candidate); 28 } 29 } 30 return eligibleAdvisors; 31 }
该方法的功能是从Advisor列表中筛选出所有和clazz匹配的增强列表,根据当前增强是否是引介增强(IntroductionAdvisor接口实现)分别调用重载的canApply方法进行判断当前Advisor和当前的clazz是否匹配,所以判断是否匹配的逻辑就在canApply方法中。
canApply方法源码如下:
1 /** 2 * 判断当前增强advisor是否匹配当前的目标类targetClass 3 * */ 4 public static boolean canApply(Advisor advisor, Class<?> targetClass) { 5 //调用内部canApply方法 6 return canApply(advisor, targetClass, false); 7 } 8 9 /** 10 * 功能同上 11 * @param advisor:增强对象 12 * @param targetClass:目标类 13 * @param hasIntroductions:是否有引介增强 14 * */ 15 public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { 16 if (advisor instanceof IntroductionAdvisor) { 17 /** 18 * 如果是引介增强,则调用IntroductionAdvisor的getClassFilter.matches方法判断是否匹配 19 * */ 20 return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); 21 } 22 else if (advisor instanceof PointcutAdvisor) { 23 /** 24 * 如果是普通增强,调用canApply方法判断是否匹配 25 * */ 26 PointcutAdvisor pca = (PointcutAdvisor) advisor; 27 return canApply(pca.getPointcut(), targetClass, hasIntroductions); 28 } 29 else { 30 // It doesn't have a pointcut so we assume it applies. 31 return true; 32 } 33 }
1 public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { 2 Assert.notNull(pc, "Pointcut must not be null"); 3 if (!pc.getClassFilter().matches(targetClass)) { 4 return false; 5 } 6 7 MethodMatcher methodMatcher = pc.getMethodMatcher(); 8 if (methodMatcher == MethodMatcher.TRUE) { 9 // No need to iterate the methods if we're matching any method anyway... 10 return true; 11 } 12 13 IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; 14 if (methodMatcher instanceof IntroductionAwareMethodMatcher) { 15 introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; 16 } 17 18 Set<Class<?>> classes = new LinkedHashSet<>(); 19 if (!Proxy.isProxyClass(targetClass)) { 20 classes.add(ClassUtils.getUserClass(targetClass)); 21 } 22 classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); 23 24 for (Class<?> clazz : classes) { 25 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); 26 for (Method method : methods) { 27 if (introductionAwareMethodMatcher != null ? 28 introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : 29 methodMatcher.matches(method, targetClass)) { 30 return true; 31 } 32 } 33 } 34 35 return false; 36 }
通过第一步和第二步已经得到了需要织入增强的目标对象TargetSource和需要织入的所有增强Advisor数组,最后一步就是调用createProxy方法将这两者合并起来创建一个目标对象的代理过程,createProxy方法源码如下:
1 /** 2 * 创建代理 3 * */ 4 protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { 5 6 if (this.beanFactory instanceof ConfigurableListableBeanFactory) { 7 AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); 8 } 9 10 /** 11 * 1.创建代理工厂类,并复制当前类的属性 12 * */ 13 ProxyFactory proxyFactory = new ProxyFactory(); 14 proxyFactory.copyFrom(this); 15 16 if (!proxyFactory.isProxyTargetClass()) { 17 if (shouldProxyTargetClass(beanClass, beanName)) { 18 proxyFactory.setProxyTargetClass(true); 19 } 20 else { 21 evaluateProxyInterfaces(beanClass, proxyFactory); 22 } 23 } 24 25 /** 26 * 2.设置代理工厂属性,将增强数组advisors和目标对象targetSource加入到代理工厂中 27 * */ 28 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); 29 proxyFactory.addAdvisors(advisors); 30 proxyFactory.setTargetSource(targetSource); 31 customizeProxyFactory(proxyFactory); 32 33 proxyFactory.setFrozen(this.freezeProxy); 34 if (advisorsPreFiltered()) { 35 proxyFactory.setPreFiltered(true); 36 } 37 /** 38 * 3.调用代理工厂类的getProxy方法创建代理对象 39 * */ 40 return proxyFactory.getProxy(getProxyClassLoader()); 41 }
从源码可以看出,主要逻辑就是构建了一个ProxyFactory对象,然后是给ProxyFactory对象的属性进行赋值,并且将增强属性和目标对象都传到代理工厂ProxyFactory中,而创建代理的过程最终是调用了ProxyFactory的getProxy方法进行创建,逻辑如下:
1 /** 创建代理对象*/ 2 public Object getProxy(@Nullable ClassLoader classLoader) { 3 //创建AopProxy对象,然后调用AopProxy对象的getProxy方法 4 return createAopProxy().getProxy(classLoader); 5 } 6 7 /** 创建AopProxy对象 */ 8 protected final synchronized AopProxy createAopProxy() { 9 if (!this.active) { 10 activate(); 11 } 12 //先获取AopProxy工厂,然后创建AopProxy对象 13 return getAopProxyFactory().createAopProxy(this); 14 } 15 16 @Override 17 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { 18 /** 19 * 判断条件选取是采用 JDK动态代理还是CGLIB代理 20 * isOptimize: 判断是否采用优化策略,只有CGLIB代理才有效 21 * isProxyTargetClass: 该属性对于<aop:aspectj-autoproxy/>标签中的proxy-target-class属性的值. 22 * 表示是否代理目标类本身,而不是目标类的接口 23 * 比如当前目标类为 GoodsServiceImpl 实现类 GoodsService接口 24 * 如果该属性为false时,则创建的代理是代理的GoodsService接口,需要用JDK动态代理 25 * 如果该属性为true时,则创建的代理是代理的GoodsServiceImpl本身,所以必须采用CGLIB来创建代理 26 * hasNoUserSuppliedProxyInterfaces :判断是否存在代理接口 27 * */ 28 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { 29 Class<?> targetClass = config.getTargetClass(); 30 if (targetClass == null) { 31 throw new AopConfigException("TargetSource cannot determine target class: " + 32 "Either an interface or a target is required for proxy creation."); 33 } 34 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { 35 /** 如果目标对象是一个接口,则创建JDK动态代理对象 */ 36 return new JdkDynamicAopProxy(config); 37 } 38 /** 39 * 如果目标对象不是一个接口,则创建 CGLIB代理对象 40 * */ 41 return new ObjenesisCglibAopProxy(config); 42 } 43 else { 44 /** 创建 JDK动态代理对象 */ 45 return new JdkDynamicAopProxy(config); 46 } 47 }
该方法中对于AOP的参数进行了判断,判断当前的对象是采用JDK动态代理还是CGLIB代理,则分别创建不同的代理对象AopProxy实现类,至于如何选择JDK动态代理还是CGLIB代理,大致规则如下:
(*** 重点 ***)
1、如果目标对象实现了接口,默认情况下会采用JDK动态代理;但是可以通过配置 proxy-target-class属性的值为true强制使用CGLIB代理,则代理的是目标对象的本身
2、如果目标对象没有实现接口,那么必须采用CGLIB创建代理对象
到目前为止已经知道了如何一步一步创建的代理了,接下来就是不同类型的代理来对目标对象创建代理对象的逻辑了,主要是通过调用AopProxy对象的getProxy方法创建,不同类型的实现分别如下:
1、JDK动态代理创建代理对象
JDK动态代理创建对象是通过代理JdkDynamicAopProxy实现的,而JdkDynamicAopProxy实现了InvocationHandler接口
1 /** 2 * JDK动态代理创建代理对象 3 * */ 4 @Override 5 public Object getProxy() { 6 //调用内部重载方法getProxy 7 return getProxy(ClassUtils.getDefaultClassLoader()); 8 } 9 10 @Override 11 public Object getProxy(@Nullable ClassLoader classLoader) { 12 13 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); 14 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); 15 //创建代理实例,并且代理实现就是JdkDynamicAopProxy本身 16 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 17 }
最终通过Proxy.newProxyInstance方法创建了代理对象,而代理执行者就是this,也就是JdkDynamicAopProxy本身,所以目标对象的所有方法执行都会执行到JdkDynamicAopProxy对象的invoke方法
注:此处涉及到Java的动态代理技术,不懂的同学可以参考文章:Java技术整理--反射机制及动态代理详解
既然目标对象的方法执行最终都会执行JdkDynamicAopProxy的invoke方法,所以核心就在于该方法的实现,源码如下:(以下是AOP动态代理最终的核心逻辑)
1 @Override 2 @Nullable 3 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 4 Object oldProxy = null; 5 boolean setProxyContext = false; 6 7 /** 获取目标对象 */ 8 TargetSource targetSource = this.advised.targetSource; 9 Object target = null; 10 11 try { 12 //处理equals方法 13 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { 14 return equals(args[0]); 15 } 16 //处理hash方法 17 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 18 return hashCode(); 19 } 20 //如果目标对象是DecoratingProxy类型,则返回目标对象的最终对象类型 21 else if (method.getDeclaringClass() == DecoratingProxy.class) { 22 return AopProxyUtils.ultimateTargetClass(this.advised); 23 } 24 /** 25 * 如果目标对象是Advice接口类型,则直接使用反射进行调用 26 * */ 27 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && 28 method.getDeclaringClass().isAssignableFrom(Advised.class)) { 29 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 30 } 31 32 Object retVal; 33 34 /** 35 * 判断是否暴露代理对象,通过<aop:aspectj-autoproxy expose-proxy="true"/>设置 36 * 当exposeProxy为true时,AopContext会在ThreadLocal中就将代理对象设置进去,就可以通过AopContext.getCurrentProxy方法获取当前的代理对象 37 * 主要是用来解决目标对象内部调用无法织入增强的问题 38 * */ 39 if (this.advised.exposeProxy) { 40 // Make invocation available if necessary. 41 oldProxy = AopContext.setCurrentProxy(proxy); 42 setProxyContext = true; 43 } 44 45 //获取目标对象 46 target = targetSource.getTarget(); 47 //获取目标对象的Class对象 48 Class<?> targetClass = (target != null ? target.getClass() : null); 49 50 /** 获取当前方法上的拦截器链*/ 51 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 52 53 if (chain.isEmpty()) { 54 //通过反射直接调用目标对象的方法 55 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 56 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); 57 } 58 else { 59 //将拦截器链封装到MethodInvocation对象中 60 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 61 /** 然后执行拦截器链 */ 62 retVal = invocation.proceed(); 63 } 64 65 //获取方法返回结果的类型 66 Class<?> returnType = method.getReturnType(); 67 if (retVal != null && retVal == target && 68 returnType != Object.class && returnType.isInstance(proxy) && 69 !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { 70 // Special case: it returned "this" and the return type of the method 71 // is type-compatible. Note that we can't help if the target sets 72 // a reference to itself in another returned object. 73 retVal = proxy; 74 } 75 else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { 76 throw new AopInvocationException( 77 "Null return value from advice does not match primitive return type for: " + method); 78 } 79 return retVal; 80 } 81 finally { 82 if (target != null && !targetSource.isStatic()) { 83 // Must have come from TargetSource. 84 targetSource.releaseTarget(target); 85 } 86 if (setProxyContext) { 87 // 88 AopContext.setCurrentProxy(oldProxy); 89 } 90 } 91 } 92 93 @Override 94 @Nullable 95 public Object proceed() throws Throwable { 96 /** 97 * 当前所以的增强方法执行完毕后,通过反射执行目标对象的方法 98 * */ 99 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 100 return invokeJoinpoint(); 101 } 102 103 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); 104 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { 105 // Evaluate dynamic method matcher here: static part will already have 106 // been evaluated and found to match. 107 InterceptorAndDynamicMethodMatcher dm = 108 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; 109 Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); 110 if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { 111 return dm.interceptor.invoke(this); 112 } 113 else { 114 // Dynamic matching failed. 115 // Skip this interceptor and invoke the next in the chain. 116 return proceed(); 117 } 118 } 119 else { 120 /** 121 * 执行普通拦截器的逻辑 122 * */ 123 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 124 } 125 }
总结代理对象执行目标对象方法的逻辑:
1、 将所有增强封装成方法拦截器MethodInterceptor对象,生成拦截器链
2、按顺序依次执行拦截器链上所有的拦截器逻辑,直到所有的拦截器逻辑通过反射执行完成,最终会通过反射执行目标对象的方法
3、拦截器的执行顺序是先执行后置增强拦截器、再执行环绕增强拦截器、然后再执行前置增强拦截器、最终才是执行目标对象的方法
后置增强拦截器处理逻辑是先执行其他拦截器逻辑,在finally中执行后置拦截器的本身逻辑,代码如下:
1 @Override 2 public Object invoke(MethodInvocation mi) throws Throwable { 3 try { 4 /** 5 * 继续执行其他方法拦截器 6 * */ 7 return mi.proceed(); 8 } 9 finally { 10 /** 11 * 最终通过反射执行后置增强拦截器本身的逻辑 12 * */ 13 invokeAdviceMethod(getJoinPointMatch(), null, null); 14 } 15 }
异常增强拦截器处理逻辑是通过try/catch捕获拦截器链的执行,一旦抛异常就通过反射执行本身的逻辑,代码如下:
1 @Override 2 public Object invoke(MethodInvocation mi) throws Throwable { 3 try { 4 /** 5 * 执行拦截器链方法 6 * */ 7 return mi.proceed(); 8 } 9 catch (Throwable ex) { 10 if (shouldInvokeOnThrowing(ex)) { 11 /** 12 * 如果拦截器链方法抛异常,则通过反射执行异常增强本身方法 13 * */ 14 invokeAdviceMethod(getJoinPointMatch(), null, ex); 15 } 16 throw ex; 17 } 18 }
环绕增强拦截器处理逻辑是执行通过反射执行环绕增强拦截器的逻辑,而在环绕增强逻辑中会执行 JoinPoint的proceed()继续执行拦截器链路的方法,代码如下:
1 @Override 2 public Object invoke(MethodInvocation mi) throws Throwable { 3 if (!(mi instanceof ProxyMethodInvocation)) { 4 throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); 5 } 6 ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi; 7 ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi); 8 JoinPointMatch jpm = getJoinPointMatch(pmi); 9 /** 通过反射执行环绕增强的逻辑*/ 10 return invokeAdviceMethod(pjp, jpm, null, null); 11 }
前置增强拦截器处理逻辑是先执行前置拦截器本身的逻辑,然后再执行拦截器链的其他方法,代码如下:
1 @Override 2 public Object invoke(MethodInvocation mi) throws Throwable { 3 /** 通过反射先执行前置增强的本身逻辑*/ 4 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); 5 /** 继续执行拦截器链路的其他逻辑 */ 6 return mi.proceed(); 7 }
所以如果有多个前置处理器,先执行invoke方法的前置处理器会先后执行横切逻辑;而如果有多个后置处理器,先执行invoke方法的后置处理器,会后执行本身的横切逻辑
2、CGLIB动态代理创建代理对象
CGLIb代理创建代理对象是通过ObjenesisCglibAopProxy对象实现,ObjenesisCglibAopProxy继承于CglibAopProxy,获取代理的方法同样也是getProxy,实现逻辑如下:
1 @Override 2 public Object getProxy() { 3 /** 调用内部重载方法getProxy*/ 4 return getProxy(null); 5 } 6 7 @Override 8 public Object getProxy(@Nullable ClassLoader classLoader) { 9 10 try { 11 /** 获取目标对象的Class对象*/ 12 Class<?> rootClass = this.advised.getTargetClass(); 13 Class<?> proxySuperClass = rootClass; 14 if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) { 15 proxySuperClass = rootClass.getSuperclass(); 16 Class<?>[] additionalInterfaces = rootClass.getInterfaces(); 17 for (Class<?> additionalInterface : additionalInterfaces) { 18 this.advised.addInterface(additionalInterface); 19 } 20 } 21 22 23 /** 24 * 构造Enhancer对象,并设置Enhancer对象的各种属性 25 * */ 26 Enhancer enhancer = createEnhancer(); 27 if (classLoader != null) { 28 enhancer.setClassLoader(classLoader); 29 if (classLoader instanceof SmartClassLoader && 30 ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { 31 enhancer.setUseCache(false); 32 } 33 } 34 enhancer.setSuperclass(proxySuperClass); 35 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); 36 enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); 37 enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader)); 38 39 Callback[] callbacks = getCallbacks(rootClass); 40 Class<?>[] types = new Class<?>[callbacks.length]; 41 for (int x = 0; x < types.length; x++) { 42 types[x] = callbacks[x].getClass(); 43 } 44 // fixedInterceptorMap only populated at this point, after getCallbacks call above 45 enhancer.setCallbackFilter(new ProxyCallbackFilter( 46 this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); 47 enhancer.setCallbackTypes(types); 48 49 /** 调用createProxyClassAndInstance方法创建代理对象 */ 50 return createProxyClassAndInstance(enhancer, callbacks); 51 } 52 catch (CodeGenerationException | IllegalArgumentException ex) { 53 throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + 54 ": Common causes of this problem include using a final class or a non-visible class", 55 ex); 56 } 57 catch (Throwable ex) { 58 throw new AopConfigException("Unexpected AOP exception", ex); 59 } 60 } 61 62 protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) { 63 enhancer.setInterceptDuringConstruction(false); 64 enhancer.setCallbacks(callbacks); 65 /** 执行Enhancer的create方法创建代理对象*/ 66 return (this.constructorArgs != null && this.constructorArgTypes != null ? 67 enhancer.create(this.constructorArgTypes, this.constructorArgs) : 68 enhancer.create()); 69 } 70 71 public Object create() { 72 classOnly = false; 73 argumentTypes = null; 74 return createHelper(); 75 } 76 77 private Object createHelper() { 78 preValidate(); 79 Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, 80 ReflectUtils.getNames(interfaces), 81 filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter), 82 callbackTypes, 83 useFactory, 84 interceptDuringConstruction, 85 serialVersionUID); 86 this.currentKey = key; 87 Object result = super.create(key); 88 return result; 89 } 90 91 protected Object create(Object key) { 92 try { 93 ClassLoader loader = getClassLoader(); 94 Map<ClassLoader, ClassLoaderData> cache = CACHE; 95 ClassLoaderData data = cache.get(loader); 96 if (data == null) { 97 synchronized (AbstractClassGenerator.class) { 98 cache = CACHE; 99 data = cache.get(loader); 100 if (data == null) { 101 Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache); 102 data = new ClassLoaderData(loader); 103 newCache.put(loader, data); 104 CACHE = newCache; 105 } 106 } 107 } 108 this.key = key; 109 Object obj = data.get(this, getUseCache()); 110 if (obj instanceof Class) { 111 return firstInstance((Class) obj); 112 } 113 return nextInstance(obj); 114 } 115 catch (RuntimeException | Error ex) { 116 throw ex; 117 } 118 catch (Exception ex) { 119 throw new CodeGenerationException(ex); 120 } 121 }
CGLIB 是一套强大的高性能的代码生成工具包,底层通过字节码生成技术ASM框架来实现,由于直接实现ASM需要熟悉JVM内部结构以及Class文件格式和指令集,所以不推荐直接使用ASM,而CGLIB就是在ASM框架基础之上的封装。所以在继续分析CGLIB实现AOP逻辑原理之前可以先熟悉下CGLIB的用法。
2.1、CGLIB的使用案例
第一步:定义目标类
1 public class UserService { 2 3 public void addUser(){ 4 System.out.println("添加新用户"); 5 } 6 7 public void getUser(){ 8 System.out.println("查询用户信息"); 9 } 10 }
定义UserService类,注意这里是类而不是接口,因为CGLIB是原理是给目标类生成子类,而不是实现接口
第二步:定义Callback,或者说是方法拦截器,或者说就是AOP中的增强逻辑
1 package com.lucky.test.spring.cglib; 2 3 import org.springframework.cglib.proxy.MethodInterceptor; 4 import org.springframework.cglib.proxy.MethodProxy; 5 import java.lang.reflect.Method; 6 7 /** 8 * 自定义方法拦截器 9 */ 10 public class CglibMethodInterceptor implements MethodInterceptor { 11 @Override 12 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 13 14 System.out.println("前置增强方法执行"); 15 16 /** 执行父类方法 */ 17 Object result = methodProxy.invokeSuper(o, objects); 18 19 System.out.println("后置增强方法执行"); 20 return result; 21 } 22 }
自定义方法拦截器实现了CGLIB包中的MethodInterceotor接口,该接口继承之Callback接口,在实现中插入了前置增强和后置增强逻辑,并且在实现中通过MethodProxy.invokeSuper方法执行了父类的方法
第三步:创建子类
1 /** 创建目标类的子类实例*/ 2 public static Object getInstance(Class superClass, Callback callback){ 3 Enhancer enhancer = new Enhancer(); 4 //设置父类 5 enhancer.setSuperclass(superClass); 6 //设置回调,MethodInterceptor就是继承的Callback接口 7 enhancer.setCallback(callback); 8 //通过字节码生成技术,创建目标类superClass的子类实例 9 return enhancer.create(); 10 }
CGLIB创建目标类子类是通过Enhancer类的create方法创建的,所以在创建之前需要先构造一个Enhancer对象,然后设置父类、callback等属性,最后通过ASM框架的字节码生成技术创建目标类的子类
第四步:测试代码如下:
1 public static void main(String[] args){ 2 3 //新建方法拦截器对象 4 MethodInterceptor callback = new CglibMethodInterceptor(); 5 //构造目标类的子类 6 UserService userService = (UserService)getInstance(UserService.class, callback); 7 //执行目标类方法,实际执行的是子类的方法 8 userService.addUser(); 9 }
先创建Callback实现类MethodInterceptor的实例,然后调用getInstance方法传入目标类UserService.class和方法拦截器CglibMethodInterceptor对象获取目标类的子类实例,最好执行子类方法,结果如下:
1 前置增强方法执行 2 添加新用户 3 后置增强方法执行
通过CGLIB创建子类的方式,成功实现了AOP的增强逻辑织入。
2.2、Spring AOP 的CGLIB生成代理的实现逻辑总结
(**重点*)
1、获取到目标对象的Class对象
2、获取所有的增强Advisor列表,并全部封装成Callback实现类MethodIncetor对象
3、构造Enhancer对象,并设置属性将目标类和需要添加的Callback全部设置为Enhancer的属性
4、通过调用Enhancer对象的create方法通过底层ASM框架的字节码生成技术创建目标对象的子类
5、获取到目标对象的子类,通过子类的方法,在子类方法中相当于也是执行了Callback的链,和JDK的方法拦截器流程类似
6、每次执行子类方法,都会执行链路上的所有Callback的intercept方法,在方法内部执行增强逻辑,并执行invokeSuper方法执行父类(目标类)的方法