• Spring源码核心剖析


    前言

    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本身的对象。

    作者:京东科技 韩国凯

    来源:京东云开发者社区

  • 相关阅读:
    Java 不定参传参
    如何使用Python抓取PDF文件并自动下载到本地
    Prompt-to-Prompt Image Editing with Cross Attention Control
    车路协同云控平台建设实践
    【Vue】VueCLI 的使用和单文件组件(1)
    Nacos相关概念小总结
    【附源码】计算机毕业设计JAVA预约健身私教网站
    在鲲鹏服务器搭建k8s高可用集群分享
    Python-print骚操作之rich库
    2023-10-16 事业-代号z-任务管理及进度控制-分析
  • 原文地址:https://www.cnblogs.com/jingdongkeji/p/17495777.html