由《Spring的IOC的源码解析(三)》继续分析! 首先介绍一下容器命名空间句柄 ContextNamespaceHandler 位置:spring-context-*.jar的META-INF/spring-handlers 容器命名空间句柄: http\:// www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler ContextNamespaceHandler的init方法实现如下, registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
当 ContextNamespaceHandler在解析标签的时候,会调用每种标签的解析器,解析过程就会调用 AopNamespaceUtils为当前类型的标签 尝试 注册相应的BPP;下边给出一些示例,格式为: {标签-标签解析器-注册的BPP} config/ ConfigBeanDefinitionParser/ AspectJAwareAdvisorAutoProxyCreator aspectj-autoproxy/ AspectJAutoProxyBeanDefinitionParser/ AnnotationAwareAspectJAutoProxyCreator load-time-weaver/ LoadTimeWeaverBeanDefinitionParser/没有 component-scan/ ComponentScanBeanDefinitionParser/没有
继续分析AOP Proxy对象的生成过程! (1)获取能够处理目标类的advisor 首先是调用AbstractAdvisorAutoProxyCreator. getAdvicesAndAdvisorsForBean()方法,然后调用: protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //这个方法就是去beanFactory中查询全部Advisor类型的bean,然后初始化;参见(a) List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//参看(b) extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors);//排序 } return eligibleAdvisors; } (a) 获取并初始化Advisor,实现逻辑在 BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans(),其核心代码是: advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false); //查询所有注册在工厂中的Advisor的bean name or id List<Advisor> advisors = new LinkedList<>(); advisors.add(this.beanFactory.getBean(name, Advisor.class)); //初始化Advisor,同时也会初始化Advisor中的advice,生成一个advice实例;
(b) 往后又调用 AopUtils.findAdvisorsThatCanApply()方法; findAdvisorsThatCanApply调用的核心函数就是: public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); //advisor是 IntroductionAdvisor的匹配过程 } else if (advisor instanceof PointcutAdvisor) {//正常使用AOP,都是这种advisor PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); //advisor是 PointcutAdvisor的匹配过程 } else { // It doesn't have a pointcut so we assume it applies. return true; //其他的 advisor 默认要处理 } } pointcut的匹配过程如下: public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { //获取advisor中的pointcut对象,关于pointcut的使用,请参看《 spring中的pointcut 》;这里相当于把所有的advisor中的pointcut都拿来匹配一遍,看看是否满足 return false; }
MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; }
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; }
Set<Class<?>> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } }
return false; }
最终,返回所有适合代理类的advisor
(2)创建AOP代理 protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); // 为bean设置属性org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass,值是beanClass } ProxyFactory proxyFactory = new ProxyFactory(); //代理工厂 proxyFactory.copyFrom(this); //为代理工厂设置proxyTargetClass,是否初始化等参数
if (!proxyFactory.isProxyTargetClass()) { //默认应该条件为true,进入if if (shouldProxyTargetClass(beanClass, beanName)) { //判断是代理类,还是代理类的接口;判断的逻辑就是看bean的定义中,属性名为 org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass的属性的值是否设置为了true。暂时只知道 ConfigurationClassPostProcessor可以配置这个属性为true;默认是false,即代理接口 proxyFactory.setProxyTargetClass(true); //代理目标类,标记 proxyTargetClass=true } else { evaluateProxyInterfaces(beanClass, proxyFactory); //代理目标类的接口;如果是可以代理的接口,就把接口加入到ProxyFactory中,见(a) } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); //合并共用和指定拦截器到advisor,可以把advisor叫做增强器;见(b) proxyFactory.addAdvisors(advisors); //这是增强器 proxyFactory.setTargetSource(targetSource);//设置实例对象,用于代理调用代理方法是使用 customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); //生成代理对象,见(c) }
(a) 可代理的接口的定义 至少有一个方法的接口 或者 protected boolean isInternalLanguageInterface(Class<?> ifc) { return (ifc.getName().equals("groovy.lang.GroovyObject") || ifc.getName().endsWith(".cglib.proxy.Factory") || ifc.getName().endsWith(".bytebuddy.MockAccess")); } 返回false的接口 或者 protected boolean isConfigurationCallbackInterface(Class<?> ifc) { return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc || AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class)); } 返回false的接口
(b)合并共用和指定拦截器到advisor,默认没有共用拦截器 protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) { Advisor[] commonInterceptors = resolveInterceptorNames(); //把定义的拦截器包装成advisor,返回 List<Object> allInterceptors = new ArrayList<>(); if (specificInterceptors != null) { allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors.length > 0) { if (this.applyCommonInterceptorsFirst) { //默认把拦截器的执行放在最前边执行 allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } Advisor[] advisors = new Advisor[allInterceptors.size()]; for (int i = 0; i < allInterceptors.size(); i++) { advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); //包装advisor,适配方法是 DefaultAdvisorAdapterRegistry.wrap() } return advisors; }
适配过程: public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; //如果是advisor对象,不用处理 } if (!(adviceObject instanceof Advice)) { //只能是advicor or advice throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; //advice对象都包装成 DefaultPointcutAdvisor对象 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); }
(c)代理工厂生成代理对象 这里一直没有读懂aopProxyFactory对象的实例话,这里假定aopProxyFactory就是一个DefaultAopProxyFactory对象; DefaultAopProxyFactory中生成代理对象的方法: 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); //类代理,分析过程见【1】 } else { return new JdkDynamicAopProxy(config); //接口代理, 分析过程见 【2】 } } 如果不是代理接口,就使用CGLIB字节码动态代理;否则使用JDK的动态代理。
【1】 jdk动态代理 JdkDynamicAopProxy.getProxy()方法: public Object getProxy(@Nullable ClassLoader classLoader) { Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised , true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } 所以,返回的代理对象就是JDK的Proxy.newProxyInstance方法生成的,而且参数需要的 InvocationHandler对象就是当前的JdkDynamicAopProxy对象; 我们知道,JDK动态代理的实现原理就是代理对象在执行目标方法的时候,会检查当前方法是否被代理?如果被代理,那么就执行 InvocationHandler的invoke方法代替;
下边看看JDK动态代理模式下的,代理对象真正执行方法时,切面织入方法的功能是怎样实现的。 JdkDynamicAopProxy实现 InvocationHandler接口,invoke方法的核心逻辑是: List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // chain是 InterceptorAndDynamicMethodMatcher链表; 参见{1} if (chain.isEmpty()) { //跳过热交换,只是执行目标类的方法,method.invoke Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //创建 method invocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //反射方法处理过程,target参数就是被代理类的实例 //执行拦截器链和方法,参看{4} retVal = invocation.proceed(); }
{1}把增强器advisors包装成mathodMatcher链的过程 调用DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice()方法, 核心代码如下: MethodInterceptor[] interceptors = registry.getInterceptors(advisor); // registry是 DefaultAdvisorAdapterRegistry实例,这里就是把advisor中的advice包装成 MethodInterceptor,见{2} MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); //获得匹配方法;参见{3} if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { if (mm.isRuntime()) { for (MethodInterceptor interceptor : interceptors) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); //采用组合模式,将拦截器对象和匹配方法对象放在 InterceptorAndDynamicMethodMatcher对象中,得到返回值对象; } } else { interceptorList.addAll(Arrays.asList(interceptors)); } }
{2}例如:下边是默认包装关系 MethodBeforeAdvice MethodBeforeAdviceInterceptor AfterReturningAdvice AfterReturningAdviceInterceptor ThrowsAdvice ThrowsAdviceInterceptor 根据advice的解析过程可知,before 类型的advice的目标类就是MethodBeforeAdvice类的子类;advice的pointcut依赖指定的目标类是AspectJExpressionPointcut
{3}由{2}的说明可知,MethodMatcher方法对象的获取过程就是获取AspectJExpressionPointcut对象;在pointcut实例化时会解析expression表达式,逻辑如下: private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) { PointcutParser parser = initializePointcutParser(classLoader); PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length]; for (int i = 0; i < pointcutParameters.length; i++) { pointcutParameters[i] = parser.createPointcutParameter( this.pointcutParameterNames[i], this.pointcutParameterTypes[i]); } return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()), this.pointcutDeclarationScope, pointcutParameters); //expression的对象类是 PointcutExpressionImpl } 需要说明的是,AspectJExpressionPointcut类实现IntroductionAwareMethodMatcher、MethodMatcher接口;
{4}循环处理拦截器链,使用matcher匹配,然后调用拦截器的invoke方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { //所有 advice都调用完之后,调用这里,但是after advice是逆向调用的,所有代理方法会在after adviec之前之前执行 return invokeJoinpoint(); } //other code if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { //匹配;见{5}分析 return dm.interceptor.invoke(this); //调用;参见{6} } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); //如果匹配失败,跳过当前advisor,继续下一个 }
{5}可知匹配过程就是AspectJExpressionPointcut的matches方法逻辑过程; {6}看看典型advice的处理过程 before advice的 MethodBeforeAdviceInterceptor调用过程如下: public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); // AspectJMethodBeforeAdvice.before方法,这里就是调用before通知在切面里定义的执行方法 return mi.proceed(); //跳转到 ReflectiveMethodInvocation. proceed()方法,实现调用多个advice的功能 }
AspectJMethodBeforeAdvice.before(){ invokeAdviceMethod(getJoinPointMatch(), null, null); }
after-returning的AfterReturningAdviceInterceptor调用过程如下: public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); //跳转到 ReflectiveMethodInvocation. proceed()方法,实现调用多个advice的功能 this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); //调用后处理方法 return retVal; }
AspectJAfterReturningAdvice.afterReturning(){ if (shouldInvokeOnReturnValueOf(method, returnValue)) { invokeAdviceMethod(getJoinPointMatch(), returnValue, null); } } 可见,所有的advice都是先执行before advice 再执行after-returning advice ;所有的advice都执行完之后,执行被代理的方法;因为after advice是逆向调用的,所以被代理的方法会在after advice之前调用。
around advice通知是怎么实现的呢? 看到DefaultAdvisorAdapterRegistry类的wrap方法: if (adviceObject instanceof Advisor) { //advice 不是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); //advice 都在这里处理,被适配成 DefaultPointcutAdvisor对象 }
再看拦截器方法链——也就是advice的方法封装,也是DefaultAdvisorAdapterRegistry的方法: public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { //around advice的处理类 AspectJAroundAdvice实现了 MethodInterceptor接口,所以就是around advice的方法拦截器就是 AspectJAroundAdvice对象 interceptors.add((MethodInterceptor) advice); } 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[interceptors.size()]); } 下边看方法拦截器的调用过程: public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); } ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi; ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi); //返回一个 MethodInvocationProceedingJoinPoint对象,这个对象就是在切面中定义的around方法的实参 JoinPointMatch jpm = getJoinPointMatch(pmi); return invokeAdviceMethod(pjp, jpm, null, null); //调用父类的方法;参见{7} }
{7}advice方法的调用,核心就是下边这一句 this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs); 解释: this.aspectJAdviceMethod获取advice指定方法的Method对象; this.aspectInstanceFactory.getAspectInstance()获取一个advice所属切面aspect的实例; actualArgs是方法参数; 也就是method.invoke(object,args)而已;
before advice,after-returning advice在调用advice方法时,会调用下一个advice的方法,但是around advice没有这样做;事实上,around advice调用下一个advice方法的语句在,切面实现的方法中,从这一点上将,只有around advice的方法参数是必须要被使用的;而在around advice方法中,可以在point.proceed();语句前后加增强语句,正是“环绕”的意义所在;需要注意的是,如果有多个around advice被执行,那么point.proceed();语句后面的增强语句的执行过程像堆栈调用,即先被调用的后被执行;
到此,基于JDK的动态代理实现的AOP过程就分析完成了!
【2】 字节码代理 ObjenesisCglibAopProxy. getProxy()方法,暂时不研究了!