【spring-aop源码(一)创建AnnotationAwareAspectJAutoProxyCreator过程】
【spring-aop源码(二)创建代理对象过程】
【spring-aop源码(三)调用aop代理方法过程】
SpringBoot源码地址:https://github.com/spring-projects
SpringBoot版本:2.4.0-SNAPSHOT
SpringBoot分支:master
前言
准备工作
创建代理对象过程
总结
在上一篇文章中,描述了AnnotationAwareAspectJAutoProxyCreator的创建过程,接下来就是探讨在创建目标代理类的过程中,被代理类究竟是怎么被增强的。
切面配置类:smoketest.aop.monitor.ServiceMonitor (@Around @After @Before @AfterReturning @AfterThrowing) package smoketest.aop.monitor; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.aop.aspectj.AspectJAfterAdvice; import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator; import org.springframework.stereotype.Component; @Aspect @Component public class ServiceMonitor { @Pointcut("execution(* smoketest..*Service.*(..))") public void pointCut() { } @After(value = "pointCut()") public void afterAccess(JoinPoint joinPoint) { System.out.println("after: " + joinPoint); } @Before(value = "pointCut()") public void beforeAccess(JoinPoint joinPoint) { System.out.println("before: " + joinPoint); } @Around("pointCut()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("around:start around"); Object obj = pjp.proceed(); System.out.println("around:end around"); return obj; } @AfterReturning(value = " pointCut()") public void returnAccess(JoinPoint joinPoint) { System.out.println("return: " + joinPoint); } @AfterThrowing(throwing = "ex", pointcut = "pointCut()") public void doRecoveryActions(Throwable ex) { System.out.println("Exception thrown in the target method:" + ex); } }
smoketest.aop.SampleAopApplication(这个类实现了CommandLineRunner,springboot 会在容器创建完成后执行其run方法) package smoketest.aop; import smoketest.aop.service.HelloWorldService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SampleAopApplication implements CommandLineRunner { // Simple example shows how an application can spy on itself with AOP @Autowired private HelloWorldService helloWorldService; @Override public void run(String... args) { System.out.println("staring......"); helloWorldService.getHelloMessage(); System.out.println("ending......"); } public static void main(String[] args) { SpringApplication.run(SampleAopApplication.class, args); } }
下面是创建代理对象的调用过程,紫色部分由springboot完成,蓝色部分由spring完成,我们着重分析标记为①②的两个方法。
SpringApplication.run(Class<?> primarySource, String... args)
->SpringApplication.run(Class<?>[] primarySources, String[] args)
->SpringApplication.run(String... args)
->SpringApplication.refreshContext(ConfigurableApplicationContext context)
->SpringApplication.refresh(ApplicationContext applicationContext)
->SpringApplication.refresh(ConfigurableApplicationContext applicationContext)
->AbstractApplicationContext.refresh()
->AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)
->DefaultListableBeanFactory.preInstantiateSingletons()->AbstractBeanFactory.getBean(String name)
->AbstractBeanFactory.doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
->DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory)
->AbstractAutowireCapableBeanFactory.createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
->AbstractAutowireCapableBeanFactory.doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
->AbstractAutowireCapableBeanFactory.initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
->AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)(①)
->AbstractAutoProxyCreator.postProcessAfterInitialization(@Nullable Object bean, String beanName)
->AbstractAutoProxyCreator.wrapIfNecessary(Object bean, String beanName, Object cacheKey)(②)
① AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)该方法在创建代理对象初始化之后调用。
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; }在分析这个方法之前,我们先了解一下BeanPostProcessors。BeanPostProcessors即后置处理器。比如,后置处理器可以在普通bean初始化之前或者初始化之后给该bean加一点“料”,在上一篇文章中提到的AnnotationAwareAspectJAutoProxyCreator就是一个BeanPostProcessors,而它给代理类加的“料”就是在代理类初始化之后,再对其增强。在上一篇文章中讲到AnnotationAwareAspectJAutoProxyCreator在创建代理类之前就已经在容器中创建完成 ,因此在创建代理类的过程中会直接调用这个后置处理器,如下图所示
AnnotationAwareAspectJAutoProxyCreator会在HelloWorldService创建的过程中对其增强。具体的增强方式是怎么样的呢,继续看②。
② AbstractAutoProxyCreator.wrapIfNecessary(Object bean, String beanName, Object cacheKey)这里是具体的增强过程,从名字能看出,该方法用来给需要的对象做包装
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 如果有增强器,创建代理。 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; }从代码可以看出,该方法先获取该bean的所有增强器specificInterceptors,这里一共获取到了6个(1个默认的,5个我们定义的),如下图所示
然后该方法调用createProxy()创建经过增强后的代理类,createProxy()的代码如下
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); } //创建一个代理工厂 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } //获取所有的增强器 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); //将增强器和代理类set到代理工厂 proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); //定制代理工厂(这里方法是空的) customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } //创建代理类 return proxyFactory.getProxy(getProxyClassLoader()); }继续step into 进入ProxyFactory.getProxy()->ProxyCreatorSupport.createAopProxy()->DefaultAopProxyFactory.createAopProxy()。DefaultAopProxyFactory.createAopProxy()代码入下所示。这段代码与proxy-target-class属性有很大的关系,当为false时,表示使用jdk动态代理织入增强,当为true时,表示使用CGlib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGlib动态代理。springboot的proxy-target-class默认为true,而且代理类没有声明接口,这里直接返回ObjenesisCglibAopProxy(config)。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (!IN_NATIVE_IMAGE &&(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); } else { return new JdkDynamicAopProxy(config); } }确定了代理模式后,回到ProxyFactory.getProxy()再step into进入CglibAopProxy.getProxy(),CglibAopProxy.getProxy()代码如下所示。CglibAopProxy.getProxy()生成代理类并创建代理实例。
public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource()); } try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass; if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // Validate the class, writing log messages as necessary. validateClassIfNecessary(proxySuperClass, classLoader); // Configure 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)); 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); // 生成代理类并创建代理实例。 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); } }最后,使用AnnotationAwareAspectJAutoProxyCreator后置处理器动态代理增强之后的代理类如下图所示。
再经过后续一些步骤,增强后的代理类被创建成功,放入容器中,供后续调用。
关键词:spring-aop、JDK动态代理、CGlib动态代理、创建动态代理类、增强器。