关于spring:Spring源码核心剖析-京东云技术团队

106次阅读

共计 9992 个字符,预计需要花费 25 分钟才能阅读完成。

前言

SpringAOP 作为 Spring 最外围的能力之一,其重要性显而易见。而后须要晓得的是 AOP 并不只是 Spring 特有的性能,而是一种思维,一种通用的性能。而 SpringAOP 只是在 AOP 的根底上将能力集成到 SpringIOC 中,使其作为 bean 的一种,从而咱们可能很不便的进行应用。

一、SpringAOP 的应用形式

1.1 应用场景

当咱们在日常业务开发中,例如有些功能模块是通用的(日志、权限等),或者咱们须要在某些性能前后去做一些加强,例如在某些办法执行后发送一条 mq 音讯等。

如果咱们将这些通用模块代码与业务代码放在一块,那么每个业务代码都要写这些通用模块,保护老本与耦合状况都非常重大。

因而,咱们能够将此模块形象进去,就有了”切面“的概念。

1.2 罕用形式

AOP 的应用形式绝对比较简单,首先咱们须要实现业务代码

@Service
public class AopDemo implements AopInterface{public Student start(String name) {System.out.println("执行业务逻辑代码.....");
        return new Student(name);
    }

}

业务逻辑比较简单,接管一个 name 参数。

接下来咱们须要创立其对应的切面

// 将该切面退出 spring 容器
@Service
// 申明该类为一个切面
@Aspect
class AopAspect {

    // 申明要进行代理的办法
    @Pointcut("execution(* com.example.demo.aop.AopInterface.start(..))")
    public void startAspect() {}

    // 在办法执行之前的逻辑
    @Before(value = "startAspect()")
    public void beforeAspect() {System.out.println("业务逻辑前代码.....");
    }

    // 在办法执行之后的逻辑
    @After(value = "startAspect()")
    public void afterAspect() {System.out.println("业务逻辑后代码.....");
    }

    // 围绕办法前后的逻辑
    @Around("startAspect()")
    public Object aroundAspect(ProceedingJoinPoint point) throws Throwable {Object[] requestParams = point.getArgs();
        String name = requestParams[0].toString();
        System.out.println("传入参数:" + name);
        requestParams[0] = "bob";
        return point.proceed(requestParams);
    }

}

能够看到,首先须要咱们指明要代理的对象及办法,而后依据须要抉择不同的注解即可实现代理对象。

传入参数:tom
业务逻辑前代码.....
执行业务逻辑代码.....
业务逻辑后代码.....

二、SpringAOP 源码解析

2.1 被代理对象的开始 initializeBean

依据下面的应用状况,咱们晓得只须要申明对应的注解即可,不须要其余额定的配置,而后咱们取得的 bean 对象就曾经是被代理的了,那么咱们能够推断代理对象的过程肯定是产生在 bean 创立的过程的。

咱们回顾一下创立 bean 的流程

  1. 实例化 bean
  2. 拆卸属性
  3. 初始化 bean

只有第三步初始化 bean 的时候才会有机会进行代理。

找到对应的代码地位:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      // 前置处理器
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
     //...
   try {
      // 对象的初始化办法
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   if (mbd == null || !mbd.isSynthetic()) {
      // 后置处理器,AOP 开始的中央
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

2.2 后置处理器 applyBeanPostProcessorsAfterInitialization

后置处理器会执行那些实现了后置处理器接口的代码:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   // 获取所有的后置处理器
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      // 实现其要执行的办法
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {return result;}
      result = current;
   }
   return result;
}

而 AOP 的后置处理器就是其中的一个:AbstractAutoProxyCreator

其对应的办法为(以下代码不为同一个类,而是对应的执行程序):

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         // 执行到上面办法
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 创立代理对象
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
}

protected Object createProxy(Class beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {

        // 获取 advisors
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);
        }

        // Use original ClassLoader if bean class not locally loaded in overriding class loader
        ClassLoader classLoader = getProxyClassLoader();
        if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}
    // 通过代理工厂创立代理对象
        return proxyFactory.getProxy(classLoader);
}

public Object getProxy(@Nullable ClassLoader classLoader) {
    // 首先获取对应的代理
        return createAopProxy().getProxy(classLoader);
}

// 该办法依据要被代理的类抉择应用 jdk 代理还是 cglib 代理
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!NativeDetector.inNativeImage() &&
                (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {Class targetClass = config.getTargetClass();
      // 如果被代理的类是一个接口则应用 jdk 代理
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass))             {return new JdkDynamicAopProxy(config);
            }
      // 否则应用 cglib 代理
            return new ObjenesisCglibAopProxy(config);
        }
        else {
      // 依据配置抉择强制应用 jdk 代理
            return new JdkDynamicAopProxy(config);
        }
}

咱们晓得,代理形式有 jdk 动静代理与 cglib 动静代理两种形式,而咱们一个 bean 应用那种代理形式则由上述的办法决定。

至此,咱们曾经确定了应用那种 代理形式 获取代理对象。

2.3 获取代理对象

从上文中,咱们曾经确定了选用何种形式构建代理对象。接下来就是通过不同的形式是如何获取代理对象的。

看懂本章须要实现理解 jdk 动静代理或者 cglib 动静代理的形式。

2.3.1 JDK 代理

首先在获取代理对象时抉择 JdkDynamicAopProxy

public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy:" + this.advised.getTargetSource());
   }
   // 这里通过反射创立代理对象
   return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

当被代理 对象执行被代理的办法 时,会进入到此办法。(jdk 动静代理的概念)

JDK 通过反射创建对象,效率上来说绝对低一些。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        try {
            // 获取被代理对象的所有切入点
            List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 如果调用链路为空阐明没有须要执行的切入点,间接执行对应的办法即可
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // 如果有切入点的话则依照切入点程序开始执行
                MethodInvocation invocation =
                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();}
            
            return retVal;
        }
}

invocation.proceed(); 这个办法就是通过递归的形式执行所有的调用链路。

public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();
   }

   Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
      InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
      Class targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
      if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);
      }
      else {
         // 继续执行
         return proceed();}
   }
   else {// 如果调用链路还继续的话,下一个办法仍会调用 proceed()
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

2.3.2 cglib 代理

public Object getProxy(@Nullable ClassLoader classLoader) {

   try {
      // 配置 CGLIB Enhancer...
      Enhancer enhancer = createEnhancer();
      if (classLoader != null) {enhancer.setClassLoader(classLoader);
         if (classLoader instanceof SmartClassLoader &&
               ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);
         }
      }
      enhancer.setSuperclass(proxySuperClass);
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

      //1. 获取回调函数, 对于代理类上所有办法的调用,都会调用 CallBack,而 Callback 则须要实现 intercept()办法
      Callback[] callbacks = getCallbacks(rootClass);
      Class[] types = new Class[callbacks.length];
      for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      //2. 创立代理对象
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of" + this.advised.getTargetClass() +
            ": Common causes of this problem include using a final class or a non-visible class",
            ex);
   }
   catch (Throwable ex) {// TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex);
   }
}

能够看到咱们在创立代理对象前会先获取代理对象的所有回调函数:

首先能够看到咱们一共有 7 个回调办法,其中第一个为 AOP 相干的办法,其余的为 spring 相干。

在第一个对调对象中持有的 advised 对象中有 advisors 属性,就是对应咱们的代理类中四个切片,@Before 等等。

而后咱们看一下 createProxyClassAndInstance()都做了什么。

//CglibAopProxy 类的创立代理对象办法
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {enhancer.setInterceptDuringConstruction(false);
   enhancer.setCallbacks(callbacks);
   return (this.constructorArgs != null && this.constructorArgTypes != null ?
         enhancer.create(this.constructorArgTypes, this.constructorArgs) :
         enhancer.create());
}

//ObjenesisCglibAopProxy 继承了 CglibAopProxy 类,并覆写了其办法
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {Class proxyClass = enhancer.createClass();
        Object proxyInstance = null;

    //1. 尝试应用 objenesis 创建对象
        if (objenesis.isWorthTrying()) {
            try {proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
            }
            catch (Throwable ex) {
                logger.debug("Unable to instantiate proxy using Objenesis," +
                        "falling back to regular proxy construction", ex);
            }
        }

    //2. 依据 commit 的提交记录发现,objenesis 有可能创建对象失败,如果失败的话则选用喷射的形式创建对象
        if (proxyInstance == null) {
            // Regular instantiation via default constructor...
            try {
                Constructor ctor = (this.constructorArgs != null ?
                        proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
                        proxyClass.getDeclaredConstructor());
                ReflectionUtils.makeAccessible(ctor);
                proxyInstance = (this.constructorArgs != null ?
                        ctor.newInstance(this.constructorArgs) : ctor.newInstance());
            }
            catch (Throwable ex) {
                throw new AopConfigException("Unable to instantiate proxy using Objenesis," +
                        "and regular proxy instantiation via default constructor fails as well", ex);
            }
        }

    //
        ((Factory) proxyInstance).setCallbacks(callbacks);
        return proxyInstance;
    }

2.3.3 cglib

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

此处在 2.2 中也可看到:

能够看到返回的是其子类的对象,而不是 CglibAopProxy 自身的对象。

作者:京东科技 韩国凯

起源:京东云开发者社区

正文完
 0