:::info

:::

image.pngimage.png

image.png
image.png

springmvc中父子容器

一二级缓存 缓存的对象是一样的,三级缓存不一样
单例才能解决循环依赖,prototype无法解决,直接报错

解决循环依赖
循环依赖有两种,一种是构造器循环依赖,另一种是set循环依赖。构造器循环依赖解决不了,在spring里,构造器和实例化是一起操作的,而实例化和初始化两个操作是分开的,所以可以解决set循环依赖
解决循环依赖关键代码

  1. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  2. isSingletonCurrentlyInCreation(beanName));
  3. if (earlySingletonExposure) {
  4. if (logger.isTraceEnabled()) {
  5. logger.trace("Eagerly caching bean '" + beanName +
  6. "' to allow for resolving potential circular references");
  7. }
  8. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  9. }
  10. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
  11. Object exposedObject = bean;
  12. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  13. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  14. if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
  15. SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
  16. exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
  17. }
  18. }
  19. }
  20. return exposedObject;
  21. }
  22. protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
  23. Assert.notNull(singletonFactory, "Singleton factory must not be null");
  24. synchronized (this.singletonObjects) {
  25. if (!this.singletonObjects.containsKey(beanName)) {
  26. this.singletonFactories.put(beanName, singletonFactory);
  27. this.earlySingletonObjects.remove(beanName);
  28. this.registeredSingletons.add(beanName);
  29. }
  30. }
  31. }

DefaultListableBeanFactory

loadBeanDeifinitions

很多个重载方法,执行顺序为
String[]->String->Resoure[]->Resource

  1. // 此处获取xml文件的document对象,这个解析过程是由documentLoader完成的,从String[] -string-Resource[]- resource,最终开始将resource读取成一个document文档,根据文档的节点信息封装成一个个的BeanDefinition对象
  2. Document doc = doLoadDocument(inputSource, resource);

registerBeanDefinitions 创建对象封装到到Beandefinition

如何拓展实现自定义属性编辑器

image.png

AspectJ

实现分为 运行期织入 类加载器织入 编译器织入
AspectJWeavingEnabler

BeanFactoryPostProcessor

image.png

ConfigurationClassPostProcessor

以Springboot 的自动装配为例
自动装配大致原理是默认识别starter的META-INF/spring.factories 文件里面的值,核心是通过@Import注解去实现的,那@Import是如何实现的呢
ConfigurationClassPostProcessor会解析一些常用的注解 如@Component @ComponentScans @PropertySources @ImportResource @Import,这其中 @Import 就包含了处理

ImportSelector, ImportBeanDefinitionRegistrar, DeferredImportSelector

image.png

监听器

image.png

实例化

五种实例化方式

InstantiationAwareBeanPostProcessor 继承自 BeanPostProcessor

是在BeanPostProcessor阶段完成实例化

例子:

  1. public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
  2. @Override
  3. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  4. System.out.println("beanName:"+beanName+"----执行postProcessBeforeInstantiation方法");
  5. if (beanClass == BeforeInstantiation.class){
  6. // Enhancer enhancer = new Enhancer();
  7. // enhancer.setSuperclass(beanClass);
  8. // enhancer.setCallback(new MyMethodInterceptor());
  9. // BeforeInstantiation beforeInstantiation = (BeforeInstantiation) enhancer.create();
  10. // System.out.println("创建代理对象:"+beforeInstantiation);
  11. return new BeforeInstantiation();
  12. }
  13. return null;
  14. }
  15. @Override
  16. public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
  17. System.out.println("beanName:"+beanName+"----执行postProcessAfterInstantiation方法");
  18. return false;
  19. }
  20. @Override
  21. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  22. System.out.println("beanName:"+beanName+"----执行postProcessBeforeInitialization方法");
  23. return bean;
  24. }
  25. @Override
  26. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  27. System.out.println("beanName:"+beanName+"----执行postProcessAfterInitialization方法");
  28. return bean;
  29. }
  30. @Override
  31. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
  32. System.out.println("beanName:"+beanName+"----执行postProcessProperties方法");
  33. return pvs;
  34. }
  35. }
  1. public class BeforeInstantiation {
  2. public void doSomeThing(){
  3. System.out.println("执行do some thing....");
  4. }
  5. }
  1. <bean id="beforeInstantiation" class="com.mashibing.resolveBeforeInstantiation.BeforeInstantiation"></bean>
  2. <bean id="myInstantiationAwareBeanPostProcessor" class="com.mashibing.resolveBeforeInstantiation.MyInstantiationAwareBeanPostProcessor"></bean>
  1. public class Test {
  2. public static void main(String[] args) {
  3. ApplicationContext ac = new ClassPathXmlApplicationContext("resolveBeforeInstantiation.xml");
  4. BeforeInstantiation bean = ac.getBean(BeforeInstantiation.class);
  5. bean.doSomeThing();
  6. }
  7. }

关键源码在 createBean()方法中的

  1. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  2. /** resolveBeforeInstantiation 方法会执行继承了 InstantiationAwareBeanPostProcessor类前/后
  3. * 处理器
  4. */

反射

image.png

BeanWapper Bean包装类

这个是用来做什么的呢?其实也很简单,现在创建出一个空对象之后,还要对空对像的属性进行填充吧,那属性填充的时候是不是要做类型转换(因为我们从xml文件读取的数据肯定是字符串类型)。这里我们看它的继承就知道了:
image.png
TypeConverter:类型转换器
PropertyEditorRegistry:
PropertyAccessor:

applyMergedBeanDefinitionPostProcessors

主要做一些修改bean的描述信息

factory-method

FactoryBean

image.png
image.png

Supplier

与FactoryBean的差别
image.png

SmartInstantiationAwareBeanPostProcessor

作用:

  1. 预测类型
  2. 决定当前的构造器
  3. 处理循环依赖的时候需要使用

    getMergedLocalBeanDefinition 合并BeanDefinition父子信息

    image.png


    在执行invokeBFPP方法时,getBeanForType() 方法第一次执行getMergedLocalBeanDefinition(),将得到的RootBeanDefinition放到缓存中
    // 合并父类BeanDefinition
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

image.png

源码细节在 doCreatebean()-> createBeanInstance()-> Supplier<?> instanceSupplier = mbd.getInstanceSupplier()

lookup-method标签

解决单例引用原型

名词解释:
prototype: 原型对象,被被标识的bean,在get的时候会是一个新的对象

验证例子如:
spring配置文件为

  1. <bean id="apple" class="com.mashibing.methodOverrides.lookup.Apple" >
  2. <property name="banana" ref="banana"></property>
  3. </bean>
  4. <bean id="banana" class="com.mashibing.methodOverrides.lookup.Banana" scope="prototype">
  5. </bean>

设置apple为单例,且apple中关联的的banana为prototype,那在获取bean的时候,banana只是同一个对象,如:

  1. ApplicationContext ac = new ClassPathXmlApplicationContext("methodOverride.xml");
  2. Apple bean = ac.getBean(Apple.class);
  3. System.out.println(bean.getBanana());
  4. Apple bean2 = ac.getBean(Apple.class);
  5. System.out.println(bean2.getBanana());
  6. // 输出
  7. // com.mashibing.methodOverrides.lookup.Banana@67784306
  8. // com.mashibing.methodOverrides.lookup.Banana@67784306

可以看出, apple中的banana属性在这里是无法实现每次都获取新的banana对象。

而使用looku-method,如

  1. <bean id="apple" class="com.mashibing.methodOverrides.lookup.Apple" >
  2. <lookup-method name="getBanana" bean="banana"></lookup-method>
  3. </bean>
  4. <bean id="banana" class="com.mashibing.methodOverrides.lookup.Banana" scope="prototype">
  5. </bean>

在代码不变情况下,输出为

  1. com.mashibing.methodOverrides.lookup.Banana@11758f2a
  2. com.mashibing.methodOverrides.lookup.Banana@e720b71

就可以实现

原理其实就是通过拦截器去创建新的对象

replace-method

初始化

循环依赖

image.png
如果单纯为了解决循环依赖,那么使用二级缓存足够解决问题了。三级缓存存在的意义是为了代理,如果没有代理对象,二级缓存足以解决问题1

填充属性 populateBean

t