bean初始化过程:

大体分为三个过程bean的对象创建、属性填充、初始化事件

  1. bean的创建前事件,其中bean的创建前事件主要场景是在aop(AnnotationAwareAspectJAutoProxyCreator主要实现了InstantiationAwareBeanPostProcessor)通过对bean的创建前拦截,

将adviser方法加入到aop包下的的ProxyFactory产生一个代理类,并且会被cache。

并在后期(postProcessAfterInitialization)对目标类进行包装。最终加入到容器与对象的属性赋值。(这个阶段会属性填充混合进行)

bean创建后置事件,用的比较少

  1. 属性填充:将bean中的@Resource,@AutoWired,@Inject等属性进行诸如,如果注入的属性还没有实例化或者不存在,会再出触发bean的创建过程,

此时会出现一个循环注入(涉及到的场景是当使用事务的时候,在没有开启事务的方法中使用this.method,没有经过事务的代理。通过是在bean中自注册一个属性。使用这个自引用bean进行方法的调用)

spring采用了三级缓存策略,其中

  • 第一级为创建完的bean, singletonObjects 单例对象的cache
  • 第二级为最近正在创建的 earlySingletonObjects, 提前暴光的单例对象的Cache
  • 第三级为创建的工厂 singletonFactories 用于存储创建的对象,即执行构造器后的实例,主要解决AOP对bean的代理。

所有如果你的bean是prototype,spring用的时候才会创建并且不会使用缓存导致在属性填充的时候异常

当使用构造器注入的时候,bean需要提前知道构造器中bean的引用或者地址。此时也是无法解决循环依赖的

所以建议使用@Setter或者属性上@AutoWired或者@Resource注入。

如果存在多个实现类使用(@AutoWired,@Qualifier(“明确写入对应service的名字”)), @Resource(name=“指定service的名字”, byName->byType, 如果同时指定则为唯一。找不到会报错)

  1. 初始化事件: 初始化后例如@PostConstruct,实现InitializingBean,@bean(initMethod),指定初始化的动作,

比如

  • 1.SpringMVC的异常处理,不允许在自己项目自定义异常处理,统一使用全局,这样利于管理。包括异常后通过log打印日志,
  • 2.在使用线程池的类在init方法中增加jvm退出的钩子函数保证线程正常shutdown()
  • 3.自定义注解,在init函数中扫描指定注解,例如限流。然后将需要限流的@RequestMapping,放入到HandlerInterceptor自定义集合中,在拦截URL时进行匹配验证

当关闭时注入关闭前的事件,例如主动关闭一些网络连接,

  1. 注意

代表是aop切面,在获取某个bean,aop(AnnotationAwareAspectJAutoProxyCreator)的处理器继承了 InstantiationAwareBeanPostProcessor ,在获取bean之前进行代理处理,并根据织入表达式把符合要

AnnotationConfigApplicationContext debug入口