Spring AOP实现源码分析(3)
Spring AOP实现源码分析(三)
Spring AOP的实现可以分为三大部分
1. 注册AOP功能具体实现类
2. 普通Bean实例化时AOP的切入
3. AOP切入具体流程
下面分析BeanPostProcessor执行过程中,aop如何切入,上一节讲到,普通bean初始化会调用如下方法
// 调用AOP的真正实现方法入口 result = beanProcessor.postProcessAfterInitialization(result, beanName);aop此方法实际是继承自AbstractAutoProxyCreator, 跟踪一下 postProcessAfterInitialization的实现
创建代理实际只有两个步骤
1. 获取增强方法或者增强器
2. 根据获取到的增强器进行代理
// class @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { // 进行aop包装 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 1. 获取增强器, 下面会详细拆分 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 如果获取到aop拦截器 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 2. 创建代理 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); // 最终返回aop代理类 return proxy; }
首先跟踪 获取增强器 的逻辑
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { // 封装在函数内 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 获取增强器,其内部实现具体为以下步骤 // 1. 获取beanFactory所有的beanName // 2. 遍历所有beanName,找到声明为AspectJ的类 // 3. 对第二步的类,进行增强器提取 // 4. 将提取结果加入缓存(提升下次调用的的效率,因为每个bean都会走这个流程) // 增强器实际会根据method上的注解(Before, After...)初始化不同的类,比如 Before 注解对应 AspectJMethodBeforeAdvice List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 判断当前bean可用的增强器,因为不一定所有的增强器对当前bean适用 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
继续跟踪 创建代理 实现
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ...... // 统一处理封装所有的的增强器 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); ...... // 生成代理,并返回,生成代理会有两种方式 // 对于实现了接口的类,默认使用jdk动态代理; 对于没有实现接口的类,只能使用cglib // 对于实现了接口的类,可以强制使用cglib(通过配置proxy-target-class="true") return proxyFactory.getProxy(getProxyClassLoader()); }代理的真正实现调用过程(jdk动态代理,或者cglib)不再赘述,比如动态代理,最终会调用invoke,稍微看一下JdkDynamicAopProxy的invoke实现,内部通过chain保存了增强器调用链,实现过程类似于职责链设计模式
// class JdkDynamicAopProxy public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ...... // 获取并封装调用链chain,实际会对advisor进行转换,比如 (@Before注解)AspectJMethodBeforeAdvice 会转换为 MethodBeforeAdviceInterceptor List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 代理方法执行 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 实际执行比较有意思,会loop chain,但是需要仔细看逻辑才明白 retVal = invocation.proceed(); } ...... } public Object proceed() throws Throwable { // interceptorsAndDynamicMethodMatchers实际是上面的调用链chain,若到达队尾,则跳出 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 获取下一个interceptor Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); ...... // 这个方法,将this传了进去,里面的实现可以看出,实际在执行完当前interceptor的invoke方法后,接着执行this.proceed,即又调用回来了当前proceed方法,保证loop chain完成 return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this); } // 比如 MethodBeforeAdviceInterceptor 的实现 @Override public Object invoke(MethodInvocation mi) throws Throwable { // advice封装了advisor this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); // mi即为上面的invoke方法传入的this return mi.proceed(); }