首页 > 编程语言 >Spring AOP源码(四):创建被代理类的代理对象

Spring AOP源码(四):创建被代理类的代理对象

时间:2023-01-02 20:44:18浏览次数:65  
标签:Object 对象 beanName 代理 bean 源码 单例 AOP

  在AOP源码(三):创建AOP相关的Bean中,介绍了Spring创建AOP的Advisor、AnnotationAwareAspectJAutoProxyCreator的创建,其中被代理类的代理对象是如何创建的未做说明,下面来看看AOP代理对象的创建。   在IOC容器启动完成,容器一级缓存singletonObjects里被代理类mathCalculator对应的value为MathCalculator$$EnhancerBySpring$$9bfe5203@2543,是一个代理对象。到这里可以带出两个问题:   1、被代理类是使用代理对象调用目标方法的,被代理类的bean是否会被创建   2、代理对象是在什么时候创建   3、代理对象在什么时候放入三级缓存的

1、AOP创建被代理类实例化入口

  一般在AOP的配置中,被代理类用bean标签声明的,在IOC容器refresh()方法中,对于普通、非懒加载的bean的实例化是在finishBeanFactoryInitialization(beanFactory);方法中完成实例化、初始化、并将创建好的bean放入三级缓存中,从finishBeanFactoryInitialization方法中分析被代理类相关的创建过程。

2、AOP创建被代理类的代理对象核心伪代码

  DefaultListableBeanFactory#preInstantiateSingletons 核心伪代码如下

// 实例化并初始化IOC容器中所有的单例bean
public void preInstantiateSingletons() throws BeansException {
   
   // 创建一个beanDefinitionNames的一个副本
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
   
   // 触发所有非延迟加载单例bean的初始化,遍历集合的对象
   for (String beanName : beanNames) {
      getBean(beanName);
   }
}

  当前beanDefinitionNames的包含被代理类MathCalculator的beanName,遍历beanNames,并通过getBean获取被代理类的实际bean信息。

  通过AbstractBeanFactory#getBean -> AbstractBeanFactory#doGetBeanBean -> AbstractAutowireCapableBeanFactory#createBean -> AbstractAutowireCapableBeanFactory#doCreateBean 的流程创建被代理类的bean信息。

  AbstractAutowireCapableBeanFactory#doCreateBean 核心伪代码:
 1 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
 2       throws BeanCreationException {
 3 
 4     // 用来持有创建出来的bean对象的
 5     BeanWrapper instanceWrapper = null;
 6     
 7     // 创建被代理类的bean实例(反射,无参构造方法实例化被代理类)
 8     instanceWrapper = createBeanInstance(beanName, mbd, args);
 9     
10     // 从包装类中获取原始bean
11     Object bean = instanceWrapper.getWrappedInstance();
12 
13     // 初始化返回的bean对象:exposedObject,此时仍然为被代理类MathCalculator的bean实例对象
14     Object exposedObject = bean;
15 
16     // 对bean的属性进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean
17     populateBean(beanName, mbd, instanceWrapper);
18     
19     // 执行初始化逻辑,此处返回代理类的代理对象
20     exposedObject = initializeBean(beanName, exposedObject, mbd);
21     
22     // 返回被代理类的代理对象
23     return exposedObject;
24 }

  当执行完createBeanInstance(beanName, mbd, args);步骤,此时instanceWrapper为被代理类MathCalculator的bean实例对象。

  初始化返回的bean对象内容,exposedObject为被代理类MathCalculator的bean实例对象。

  populateBean(beanName, mbd, instanceWrapper);对实例化的bean做属性填充,不涉及返回对象exposedObject的处理,该方法可不做考虑。

  初始化方法initializeBean(beanName, exposedObject, mbd);执行完成,exposedObject对象已变成被代理类MatchCalculator的代理对象了。   通过上述分析,可以简单的回答最开始抛出的问题了:   1、被代理类是使用代理对象调用目标方法的,被代理类是否会被创建     被代理类的bean会被创建   2、代理对象是在什么时候创建     在被代理类bean初始化阶段创建的代理对象

3、被代理类的bean如何被代理对象替换的

  到目前为止已经知道被代理类在初始化阶段会返回代理对象,

  AbstractAutowireCapableBeanFactory#initializeBean 初始化Bean信息核心伪代码:
 1 // 初始化bean信息
 2 protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
 3   
 4    Object wrappedBean = bean;
 5    
 6    //如果mdb不为null || mbd不是"synthetic"。只有AOP相关的prointCut配置或者Advice配置才会将 synthetic设置为true
 7    if (mbd == null || !mbd.isSynthetic()) {
 8       // 初始化Bean的前置处理方法
 9       wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
10    }
11 
12   //调用初始化方法,通过反射执行
13   invokeInitMethods(beanName, wrappedBean, mbd);
14    
15    //如果mbd为null || mbd不是"synthetic"
16    if (mbd == null || !mbd.isSynthetic()) {
17       // 初始化Bean的后置处理方法
18       wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
19    }
20 
21    //返回包装后的Bean
22    return wrappedBean;
23 }

  在Bean的初始化后置处理之前,wrappedBean都为被代理类的MatchCalculator的对象,执行完applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)方法,wrappedBean就变为被代理类的代理对。

  此处我们可以得出结论,AOP被代理类的代理对象是在初始化Bean的后置处理创建并返回的。

初始化bean的后置处理器核心伪代码:

  AbstractAutoProxyCreator#postProcessAfterInitialization
 1 // Bean初始化的后置处理
 2 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
 3    if (bean != null) {
 4       // 获取缓存中当前bean的key:如果beanName不为空,则以beanName为key,此处为mathCalculator
 5       Object cacheKey = getCacheKey(bean.getClass(), beanName);
 6       // 当前bean是否已经被提前代理
 7       if (this.earlyProxyReferences.remove(cacheKey) != bean) {
 8          // bean未被提前代理,若需要代理,创建代理对象并返回
 9          return wrapIfNecessary(bean, beanName, cacheKey);
10       }
11    }
12    return bean;
13 }

  AbstractAutoProxyCreator#wrapIfNecessary 核心伪代码:

 1 // bean生成代理对象的类型,key=beanName, value为生成代理类的Class对象
 2 private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
 3 
 4 // 已经被代理的beanName的容器,value=true 表示key=beanName已经生成了代理对象
 5 private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
 6 
 7 // 代理对象创建
 8 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
 9     
10     // 这里isInfrastructureClass()用于判断当前bean是否为Spring系统自带的bean,自带的bean是不用进行代理的;
11     // shouldSkip()则用于判断当前bean是否应该被略过
12     if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
13        this.advisedBeans.put(cacheKey, Boolean.FALSE);
14        return bean;
15     } 
16     
17    // 获取当前bean的Advices和Advisors, 添加ExoseInvocationInterceptor的处理链并放在索引为0的位置
18    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
19    
20    // 对当前bean的代理状态进行缓存
21    if (specificInterceptors != DO_NOT_PROXY) {
22       // 对当前bean的代理状态进行缓存
23       this.advisedBeans.put(cacheKey, Boolean.TRUE);
24       
25       // 根据获取到的Advices和Advisors为当前bean生成代理对象
26       Object proxy = createProxy(
27             bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
28       // 缓存生成的代理bean的类型,并且返回生成的代理bean
29       this.proxyTypes.put(cacheKey, proxy.getClass());
30       return proxy;
31    }
32 
33    this.advisedBeans.put(cacheKey, Boolean.FALSE);
34    return bean;
35 }

  到这里可以很清楚的看到,当IOC容器中有Advisor通知时,会创建被代理类MathCalCulator的代理对象并返回,将代理对象的引用设置给exposedObject变量。这里要注意一点, getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)添加了一个ExoseInvocationInterceptor的Advice,用作执行AOP责任链的控制器。

4、被代理类的代理对象是如何设置进三级缓存的

  createBean的入口是在AbstractBeanFactory#doGetBean方法中,getSingleton(String beanName, ObjectFactory singletonFactory),singletonFactory是一个函数式接口,当执行到getSingleton里的singletonFactory.getObject();时,执行创建bean的方法createBean  
 1 protected <T> T doGetBean(
 2       String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
 3       throws BeansException {
 4     Object bean;
 5     
 6     // 提前检查单例缓存中是否有手动注册的单例对象
 7     Object sharedInstance = getSingleton(beanName);
 8       
 9     // 创建单例bean的实例对象
10     if (mbd.isSingleton()) {
11         // 返回以beanName的(原始)单例对象,如果尚未注册,则使用singletonFactory创建并注册一个对象:
12         sharedInstance = getSingleton(beanName, () -> {
13            try {
14               // 为给定的合并后BeanDefinition(和参数)创建一个bean实例
15               return createBean(beanName, mbd, args);
16            }
17            catch (BeansException ex) {
18               destroySingleton(beanName);
19               throw ex;
20            }
21         });
22         // 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
23         // FactoryBean会直接返回beanInstance实例
24         bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
25     }
26         
27    // 将bean返回出去
28    return (T) bean;
29 }

  DefaultSingletonBeanRegistry#getSingleton 核心伪代码

 1 // 获取单例Bean
 2 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
 3 
 4     // 从单例对象的三级缓存中获取beanName对应的单例对象
 5     Object singletonObject = this.singletonObjects.get(beanName);
 6       
 7     // 如果单例对象获取不到
 8     if (singletonObject == null) {       
 9         // 从单例工厂中获取对象
10         singletonObject = singletonFactory.getObject();
11         // 生成了新的单例对象的标记为true,表示生成了新的单例对象
12         newSingleton = true;
13     }
14          
15      // 生成了新的单例对象
16      if (newSingleton) {
17         // 将beanName和singletonObject的映射关系添加到该工厂的单例缓存中:
18         addSingleton(beanName, singletonObject);
19      }
20 
21       // 返回该单例对象
22       return singletonObject;
23 }
  从doCreateBean中返回的exposeObject代理对象,最终在singletonObject = singletonFactory.getObject();步骤中,将代理对象赋值给singletonObject,并标记为新建的单例对象,通过addSingleton方法将代理对象设置进三级缓存中。   DefaultSingletonBeanRegistry#addSingleton 核心代码
 1 protected void addSingleton(String beanName, Object singletonObject) {
 2    synchronized (this.singletonObjects) {
 3       // 将映射关系添加到单例对象的一级缓存中
 4       this.singletonObjects.put(beanName, singletonObject);
 5       // 移除beanName在单例工厂缓存中的数据
 6       this.singletonFactories.remove(beanName);
 7       // 移除beanName在早期单例对象的高速缓存的数据
 8       this.earlySingletonObjects.remove(beanName);
 9       // 将beanName添加到已注册的单例集中
10       this.registeredSingletons.add(beanName);
11    }
12 }

代理对象在什么时候放入三级缓存的:

  与普通bean一样,都是在实例化完成之后,将返回的bean信息放入三级缓存中,只不过对于AOP的被代理类,实例化后返回的不是bean本身,而是代理类的代理对象的bean。

5、AOP创建被代理类的代理对象核心流程图

标签:Object,对象,beanName,代理,bean,源码,单例,AOP
From: https://www.cnblogs.com/RunningSnails/p/17020482.html

相关文章