Spring源码核心剖析

打印 上一主题 下一主题

主题 945|帖子 945|积分 2835

前言

SpringAOP作为Spring最核心的能力之一,其重要性不言而喻。然后需要知道的是AOP并不只是Spring特有的功能,而是一种思想,一种通用的功能。而SpringAOP只是在AOP的基础上将能力集成到SpringIOC中,使其作为bean的一种,从而我们能够很方便的进行使用。
一、SpringAOP的使用方式

1.1 使用场景

当我们在日常业务开发中,例如有些功能模块是通用的(日志、权限等),或者我们需要在某些功能前后去做一些增强,例如在某些方法执行后发送一条mq消息等。
如果我们将这些通用模块代码与业务代码放在一块,那么每个业务代码都要写这些通用模块,维护成本与耦合情况都十分严重。
因此,我们可以将此模块抽象出来,就有了”切面“的概念。
1.2 常用方式

AOP的使用方式相对比较简单,首先我们需要完成业务代码
  1. @Service
  2. public class AopDemo implements AopInterface{
  3.     public Student start(String name) {
  4.         System.out.println("执行业务逻辑代码.....");
  5.         return new Student(name);
  6.     }
  7. }
复制代码
业务逻辑比较简单,接收一个name参数。
接下来我们需要创建其对应的切面
  1. //将该切面加入spring容器
  2. @Service
  3. //声明该类为一个切面
  4. @Aspect
  5. class AopAspect {
  6.     //声明要进行代理的方法
  7.     @Pointcut("execution(* com.example.demo.aop.AopInterface.start(..))")
  8.     public void startAspect() {
  9.     }
  10.     //在方法执行之前的逻辑
  11.     @Before(value = "startAspect()")
  12.     public void beforeAspect() {
  13.         System.out.println("业务逻辑前代码.....");
  14.     }
  15.     //在方法执行之后的逻辑
  16.     @After(value = "startAspect()")
  17.     public void afterAspect() {
  18.         System.out.println("业务逻辑后代码.....");
  19.     }
  20.     //围绕方法前后的逻辑
  21.     @Around("startAspect()")
  22.     public Object aroundAspect(ProceedingJoinPoint point) throws Throwable {
  23.         Object[] requestParams = point.getArgs();
  24.         String name = requestParams[0].toString();
  25.         System.out.println("传入参数:" + name);
  26.         requestParams[0] = "bob";
  27.         return point.proceed(requestParams);
  28.     }
  29. }
复制代码
可以看到,首先需要我们指明要代理的对象及方法,然后根据需要选择不同的注解即可实现代理对象。
  1. 传入参数:tom
  2. 业务逻辑前代码.....
  3. 执行业务逻辑代码.....
  4. 业务逻辑后代码.....
复制代码
二、SpringAOP源码解析

2.1 被代理对象的开始initializeBean

根据上面的使用情况,我们知道只需要声明对应的注解即可,不需要其他额外的配置,然后我们获得的bean对象就已经是被代理的了,那么我们可以推断代理对象的过程一定是发生在bean创建的过程的。
我们回顾一下创建bean的流程

  • 实例化bean
  • 装配属性
  • 初始化bean
只有第三步初始化bean的时候才会有机会进行代理。
找到对应的代码位置:
  1. protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
  2.    Object wrappedBean = bean;
  3.    if (mbd == null || !mbd.isSynthetic()) {
  4.       //前置处理器
  5.       wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  6.    }
  7.          //...
  8.    try {
  9.       //对象的初始化方法
  10.       invokeInitMethods(beanName, wrappedBean, mbd);
  11.    }
  12.    if (mbd == null || !mbd.isSynthetic()) {
  13.       //后置处理器,AOP开始的地方
  14.       wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  15.    }
  16.    return wrappedBean;
  17. }
复制代码
2.2 后置处理器applyBeanPostProcessorsAfterInitialization

后置处理器会执行那些实现了后置处理器接口的代码:
  1. public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  2.       throws BeansException {
  3.    Object result = existingBean;
  4.    //获取所有的后置处理器
  5.    for (BeanPostProcessor processor : getBeanPostProcessors()) {
  6.       //实现其要执行的方法
  7.       Object current = processor.postProcessAfterInitialization(result, beanName);
  8.       if (current == null) {
  9.          return result;
  10.       }
  11.       result = current;
  12.    }
  13.    return result;
  14. }
复制代码
而AOP的后置处理器就是其中的一个: AbstractAutoProxyCreator
其对应的方法为(以下代码不为同一个类,而是对应的执行顺序):
  1. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  2.    if (bean != null) {
  3.       Object cacheKey = getCacheKey(bean.getClass(), beanName);
  4.       if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  5.          //执行到下面方法
  6.          return wrapIfNecessary(bean, beanName, cacheKey);
  7.       }
  8.    }
  9.    return bean;
  10. }
  11. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  12.                 // Create proxy if we have advice.
  13.                 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  14.                 if (specificInterceptors != DO_NOT_PROXY) {
  15.                         this.advisedBeans.put(cacheKey, Boolean.TRUE);
  16.       //创建代理对象
  17.                         Object proxy = createProxy(
  18.                                         bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  19.                         this.proxyTypes.put(cacheKey, proxy.getClass());
  20.                         return proxy;
  21.                 }
  22.                 this.advisedBeans.put(cacheKey, Boolean.FALSE);
  23.                 return bean;
  24. }
  25. protected Object createProxy(Class beanClass, @Nullable String beanName,
  26.                         @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  27.                 //获取advisors
  28.                 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  29.                 proxyFactory.addAdvisors(advisors);
  30.                 proxyFactory.setTargetSource(targetSource);
  31.                 customizeProxyFactory(proxyFactory);
  32.                 proxyFactory.setFrozen(this.freezeProxy);
  33.                 if (advisorsPreFiltered()) {
  34.                         proxyFactory.setPreFiltered(true);
  35.                 }
  36.                 // Use original ClassLoader if bean class not locally loaded in overriding class loader
  37.                 ClassLoader classLoader = getProxyClassLoader();
  38.                 if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
  39.                         classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
  40.                 }
  41.     //通过代理工厂创建代理对象
  42.                 return proxyFactory.getProxy(classLoader);
  43. }
  44. public Object getProxy(@Nullable ClassLoader classLoader) {
  45.     //首先获取对应的代理
  46.                 return createAopProxy().getProxy(classLoader);
  47. }
  48. //该方法根据要被代理的类选择使用jdk代理还是cglib代理
  49. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  50.                 if (!NativeDetector.inNativeImage() &&
  51.                                 (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
  52.                         Class targetClass = config.getTargetClass();
  53.       //如果被代理的类是一个接口则使用jdk代理
  54.                         if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass))                         {
  55.                                 return new JdkDynamicAopProxy(config);
  56.                         }
  57.       //否则使用cglib代理
  58.                         return new ObjenesisCglibAopProxy(config);
  59.                 }
  60.                 else {
  61.       //根据配置选择强制使用jdk代理
  62.                         return new JdkDynamicAopProxy(config);
  63.                 }
  64. }
复制代码
我们知道,代理方式有jdk动态代理与cglib动态代理两种方式,而我们一个bean使用那种代理方式则由上述的方法决定。
至此,我们已经确定了使用那种代理方式获取代理对象。
2.3 获取代理对象

从上文中,我们已经确定了选用何种方式构建代理对象。接下来就是通过不同的方式是如何获取代理对象的。
看懂本章需要实现了解jdk动态代理或者cglib动态代理的方式。
2.3.1 JDK代理

首先在获取代理对象时选择 JdkDynamicAopProxy
  1. public Object getProxy(@Nullable ClassLoader classLoader) {
  2.    if (logger.isTraceEnabled()) {
  3.       logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  4.    }
  5.    //这里通过反射创建代理对象
  6.    return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
  7. }
复制代码
当被代理对象执行被代理的方法时,会进入到此方法。(jdk动态代理的概念)
JDK通过反射创建对象,效率上来说相对低一些。
  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  2.                 try {
  3.                         // 获取被代理对象的所有切入点
  4.                         List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  5.                         // 如果调用链路为空说明没有需要执行的切入点,直接执行对应的方法即可
  6.                         if (chain.isEmpty()) {
  7.                                 // We can skip creating a MethodInvocation: just invoke the target directly
  8.                                 // Note that the final invoker must be an InvokerInterceptor so we know it does
  9.                                 // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
  10.                                 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  11.                                 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  12.                         }
  13.                         else {
  14.                                 // 如果有切入点的话则按照切入点顺序开始执行
  15.                                 MethodInvocation invocation =
  16.                                                 new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
  17.                                 // Proceed to the joinpoint through the interceptor chain.
  18.                                 retVal = invocation.proceed();
  19.                         }
  20.                        
  21.                         return retVal;
  22.                 }
  23. }
复制代码
invocation.proceed();这个方法就是通过递归的方式执行所有的调用链路。
  1. public Object proceed() throws Throwable {
  2.    // We start with an index of -1 and increment early.
  3.    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
  4.       return invokeJoinpoint();
  5.    }
  6.    Object interceptorOrInterceptionAdvice =
  7.          this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
  8.    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
  9.       InterceptorAndDynamicMethodMatcher dm =
  10.             (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
  11.       Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
  12.       if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
  13.          return dm.interceptor.invoke(this);
  14.       }
  15.       else {
  16.          // 继续执行
  17.          return proceed();
  18.       }
  19.    }
  20.    else {
  21.       // 如果调用链路还持续的话,下一个方法仍会调用proceed()
  22.       return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
  23.    }
  24. }
复制代码
2.3.2 cglib代理
  1. public Object getProxy(@Nullable ClassLoader classLoader) {
  2.    try {
  3.       //配置CGLIB Enhancer...
  4.       Enhancer enhancer = createEnhancer();
  5.       if (classLoader != null) {
  6.          enhancer.setClassLoader(classLoader);
  7.          if (classLoader instanceof SmartClassLoader &&
  8.                ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
  9.             enhancer.setUseCache(false);
  10.          }
  11.       }
  12.       enhancer.setSuperclass(proxySuperClass);
  13.       enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
  14.       enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
  15.       enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
  16.       //1.获取回调函数,对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法
  17.       Callback[] callbacks = getCallbacks(rootClass);
  18.       Class[] types = new Class[callbacks.length];
  19.       for (int x = 0; x < types.length; x++) {
  20.          types[x] = callbacks[x].getClass();
  21.       }
  22.       // fixedInterceptorMap only populated at this point, after getCallbacks call above
  23.       enhancer.setCallbackFilter(new ProxyCallbackFilter(
  24.             this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
  25.       enhancer.setCallbackTypes(types);
  26.       //2.创建代理对象
  27.       return createProxyClassAndInstance(enhancer, callbacks);
  28.    }
  29.    catch (CodeGenerationException | IllegalArgumentException ex) {
  30.       throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
  31.             ": Common causes of this problem include using a final class or a non-visible class",
  32.             ex);
  33.    }
  34.    catch (Throwable ex) {
  35.       // TargetSource.getTarget() failed
  36.       throw new AopConfigException("Unexpected AOP exception", ex);
  37.    }
  38. }
复制代码
可以看到我们在创建代理对象前会先获取代理对象的所有回调函数:

首先可以看到我们一共有7个回调方法,其中第一个为AOP相关的方法,其他的为spring相关。
在第一个对调对象中持有的 advised 对象中有 advisors 属性,就是对应我们的代理类中四个切片,@Before等等。
然后我们看一下 createProxyClassAndInstance()都做了什么。
  1. //CglibAopProxy类的创建代理对象方法
  2. protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
  3.    enhancer.setInterceptDuringConstruction(false);
  4.    enhancer.setCallbacks(callbacks);
  5.    return (this.constructorArgs != null && this.constructorArgTypes != null ?
  6.          enhancer.create(this.constructorArgTypes, this.constructorArgs) :
  7.          enhancer.create());
  8. }
  9. //ObjenesisCglibAopProxy继承了CglibAopProxy类,并覆写了其方法
  10. protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
  11.                 Class proxyClass = enhancer.createClass();
  12.                 Object proxyInstance = null;
  13.     //1.尝试使用objenesis创建对象
  14.                 if (objenesis.isWorthTrying()) {
  15.                         try {
  16.                                 proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
  17.                         }
  18.                         catch (Throwable ex) {
  19.                                 logger.debug("Unable to instantiate proxy using Objenesis, " +
  20.                                                 "falling back to regular proxy construction", ex);
  21.                         }
  22.                 }
  23.     //2.根据commit的提交记录发现,objenesis有可能创建对象失败,如果失败的话则选用放射的方式创建对象
  24.                 if (proxyInstance == null) {
  25.                         // Regular instantiation via default constructor...
  26.                         try {
  27.                                 Constructor ctor = (this.constructorArgs != null ?
  28.                                                 proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
  29.                                                 proxyClass.getDeclaredConstructor());
  30.                                 ReflectionUtils.makeAccessible(ctor);
  31.                                 proxyInstance = (this.constructorArgs != null ?
  32.                                                 ctor.newInstance(this.constructorArgs) : ctor.newInstance());
  33.                         }
  34.                         catch (Throwable ex) {
  35.                                 throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
  36.                                                 "and regular proxy instantiation via default constructor fails as well", ex);
  37.                         }
  38.                 }
  39.     //
  40.                 ((Factory) proxyInstance).setCallbacks(callbacks);
  41.                 return proxyInstance;
  42.         }
复制代码
2.3.3 cglib

此处有个遇到的问题,当我在debug的时候,发现怎么都进不去 createProxyClassAndInstance(),百思不得其解,然后看到IDEA旁边有一个向下的箭头,代表该方法可能其子类被覆写了。然后在其子类处打断点果然发现是其子类的实现。
此处在2.2中也可看到:

可以看到返回的是其子类的对象,而不是CglibAopProxy本身的对象。
作者:京东科技 韩国凯
来源:京东云开发者社区

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

去皮卡多

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表