spring笔记


这里只是做一部分笔记,用来配合看源码比较好

Spring要学习的点:

1.IOC
2.AOP
3.SpringMvc
4.设计模式
5.事务管理

先来看IOC

bean的生命周期:

  1. 实例化(getWrappedInstance())
  2. 注入属性(populateBean)
  3. 初始化(initializeBean)
  4. 销毁 (destory())

创建的这三个阶段是在具体beanFactory工厂类的doCreateBean里完成的

三级缓存:

  1. 一级缓存:singletonObjects,单例池,(内容:用于存放走完完整bean创建周期的bean)。

  2. 二级缓存:earlySingletonObjects ,当出现循环依赖的时候,即判断某个bean正在创建中的状态的时候,就会把这个bean往二级缓存里面存一份。(内容:没有经过初始化的原始对象或者代理对象)(如果需要AOP会提前进行AOP再将代理对象存进去)。
    注入属性的时候会从单例池和二级缓存里面找。(作用:之所以需要二级缓存是因为在有多个属性循环依赖的时候,可能会产生多个代理对象,那么第一个产生的代理对象先放到二级缓存里面去的话,后面的先从二级缓存获取,获取不到才会再产生代理对象,这样就能保证始终都只有一个代理对象了)

  3. 三级缓存:singletonFactories,存放一个getEarlyBeanReference的工厂。当一个单例bean实例化之后就调用addSingletonFactory方法会往里面存factory的lambda表达式。(作用:而这些信息之所以要在属性注入和初始化之前存进三级缓存,是因为如果要进行AOP的话,需要从三级缓存里面取出必要的信息来进行动态代理)

bean的循环依赖创建流程:(比如A依赖B,B依赖A)
一般进行AOP的时机是在属性注入以后,但是有循环依赖的话,这里A的AOP是在属性注入的时候创建的,所以A在属性注入之后判断如果已经AOP过了,就不会再AOP了。
A的流程:

  1. 通过扫描解析出beandefination,用于存在bean创建所需要的各种信息。
  2. 在CreatingSet中把bean名字加进去,表示这个bean正在创建中。
  3. 实例化bean,再接着给三级缓存存放该bean的工厂信息。
  4. 填充属性——》从单例池找该属性B的bean,没有的话就创建一个。

B的流程:

4.1. 实例化该属性B的bean对象——》给B填充属性A,在单例池和二级缓存找不到,又发现通过CreatingSet查到要填充的A正在被创建,那就是循环依赖了。这个时候会去判断A需不需要进行AOP,需要的话就在这里从三级缓存获取工厂信息,进行AOP,并把A产生的代理对象放入二级缓存。
4.2. 这时候就从二级缓存中找出刚第一个要创建的bean的对象。把它注入到第二个bean中去。
4.3. B进行AOP,再放入到单例池

A的流程:

  1. 接着A上面的操作,把B填充进去。
  2. 放入单例池

AOP

代理对象:代理对象中的属性值为空,它有一个target字段,而这个target存的是对原对象的引用,所有的属性赋值都在原对象中。(也就是bean的属性赋值阶段一直是对原始对象进行赋值的)

AOP最终进行动态代理的类是AbstractAutoProxyCreator这个类。
提前进行AOP调用的是getEarlyBeanReference,正常进行AOP是在postProcessAfterInitialization方法中。他们都是调用wrapIfNecessary来进行动态代理的。

提前进行AOP是在getSingleton里,如果一级二级缓存都获取不到,就会通过三级缓存进行AOP获取bean,并把结果放到二级缓存里,再删除三级缓存里的工厂,三级缓存中存储的getEarlyReference方法会进行AOP。

这是getEarlyBeanReference方法

    public Object getEarlyBeanReference(Object bean, String beanName) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        this.earlyProxyReferences.put(cacheKey, bean);
        //通过wrapIfNecessary返回代理对象
        return this.wrapIfNecessary(bean, beanName, cacheKey);
    }

这是postProcessAfterInitialization方法

    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //通过wrapIfNecessary返回代理对象
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

可以来看看wrapIfNecessary方法是如何生成代理对象的。

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
            //getAdvicesAndAdvisorsForBean会去获取所有可用的增强点
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                //通过增强点来进行动态代理
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }
  1. 通过getAdvicesAndAdvisorsForBean去获得增强点。
    而getAdvicesAndAdvisorsForBean最终会通过buildAspectJAdvisors来找到所有带有@Aspect注解的增强点。
  2. 通过createProxy创建代理对象。
    最终通过JdkDynamicAopProxy或者CglibAopProxy的getProxy来创建代理对象。

Spring的扩展点(所有的扩展点接口都实现了BeanPostProcessor)

影响多个bean的接口:

1.InstantiationAwareBeanPostProcessor接口

  • resolveBeforeInstantiation调用点
    调用时机:在实例化前调用
    就是for循环调用所有的InstantiationAwareBeanPostProcessor接口 ,这个调用点在具体工厂类的createBean方法里调用(如AbstractAutowireCapableBeanFactory),并返回一个bean,如果为空则调用doCreateBean去创建bean。
  • postProcessAfterInstantiation调用点
    调用时机:在实例化后,属性赋值前调用,并且有一个返回值,来判断是否允许进行属性赋值

2.BeanPostProcessor接口

  • postProcessBeforeInitialization调用点
    调用时机:在初始化前,是一个beanPostProcessor
  • postProcessAfterInitialization调用点
    调用时机:在初始化后,是一个beanPostProcessor

只有一个bean调用的接口:

3.Aware接口

  • 第一组aware(BeanNameAware、2.BeanClassLoaderAware、BeanFactoryAware、)
    在initializeBean的invokeAwareMethods直接调用以获取资源

  • 第二组aware(EnvironmentAware、EmbeddedValueResolverAware、applicationContextAware)
    在initializeBean的applyBeanPostProcessorsBeforeInitialization里调用
    (@PostConstruct注解也是在applyBeanPostProcessorsBeforeInitialization里调用的)

  • 在initializeBean里还有一个
    applyBeanPostProcessorsAfterInitialization,这是BeanPostProcessor的另一个调用点

生命周期相关的两个接口,这也只有实现他的bean才调用:

  • InitializingBean接口
    调用时机:在initializeBean的invokeInitMethods方法里调用
    由于aware方法都是执行在这个方法前面,所以可以在这个方法里去调用aware接口去获取资源,这也是我们自定义去扩展spring的常用方式。
    自定义的方式:1.实现InitializingBean接口,2.xml里的init-method方法

  • DisableBean接口
    调用时机:bean被销毁的时候调用
    自定义方式:实现DisableBean接口

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值