在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#postProcessAfterInitialization1 // 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的方法createBean1 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。