spring-aop源码(二)创建代理对象过程

    科技2022-07-12  137

    系列文章目录

    【spring-aop源码(一)创建AnnotationAwareAspectJAutoProxyCreator过程】

    【spring-aop源码(二)创建代理对象过程】

    【spring-aop源码(三)调用aop代理方法过程】

    SpringBoot源码地址:https://github.com/spring-projects

    SpringBoot版本:2.4.0-SNAPSHOT

    SpringBoot分支:master


    文章目录

    前言

    准备工作

    创建代理对象过程

    总结


    前言

    在上一篇文章中,描述了AnnotationAwareAspectJAutoProxyCreator的创建过程,接下来就是探讨在创建目标代理类的过程中,被代理类究竟是怎么被增强的。


    准备工作

    服务类:smoketest.aop.service.HelloWorldService package smoketest.aop.service; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class HelloWorldService { @Value("${name:World}") private String name; public String getHelloMessage() { System.out.println("method:HelloWorldService|getHelloMessage()|" + name); int i = 3 / 0; return "hello"; } }

     

    切面配置类: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动态代理、创建动态代理类、增强器。

    Processed: 0.013, SQL: 8