1. Bean 定义加载
Spring 容器首先会加载 Bean 的定义信息(BeanDefinition)。这些定义信息可以通过以下方式加载:
- XML 配置文件:通过
<bean>标签定义。 - Java 配置类:通过
@Bean注解定义。 - 注解扫描:通过
@Component、@Service、@Repository等注解定义,并由@ComponentScan扫描。
2. BeanDefinition 注册
加载的 Bean 定义信息会被注册到 BeanFactory 中,具体实现类是 DefaultListableBeanFactory。每个 Bean 的定义信息包括:
- Bean 的类名。
- Bean 的作用域(如 Singleton、Prototype)。
- 依赖关系(通过构造函数或 Setter 方法注入)。
- 初始化方法和销毁方法。
3. 实例化 Bean
Spring 容器根据 BeanDefinition 实例化 Bean。实例化的过程包括:
- 选择构造函数:如果 Bean 有多个构造函数,Spring 会根据依赖关系选择合适的构造函数。
- 通过反射创建实例:Spring 使用反射机制调用构造函数创建 Bean 实例。
4. 填充 Bean 属性
在 Bean 实例化后,Spring 容器会通过依赖注入(DI)填充 Bean 的属性。依赖注入的方式包括:
- Setter 注入:通过 Setter 方法注入依赖。
- 构造函数注入:通过构造函数注入依赖。
- 字段注入:通过
@Autowired注解直接注入字段。
5. 调用 Aware 接口
如果 Bean 实现了 Spring 的 Aware 接口(如 BeanNameAware、BeanFactoryAware、ApplicationContextAware),Spring 容器会调用相应的回调方法,将相关的上下文信息注入到 Bean 中。
6. BeanPostProcessor 的前置处理
在 Bean 初始化之前,Spring 容器会调用所有注册的 BeanPostProcessor 的 postProcessBeforeInitialization 方法,允许对 Bean 进行额外的处理。
- 常见用途:
-
- 修改 Bean 的属性。
- 执行一些前置逻辑(如日志记录)。
7. 初始化 Bean
在 Bean 属性填充完成后,Spring 容器会执行 Bean 的初始化逻辑。初始化的方式包括:
- 实现
InitializingBean接口:调用afterPropertiesSet()方法。 - 使用
@PostConstruct注解:标记初始化方法。 - XML 配置中的
init-method:指定初始化方法。
8. BeanPostProcessor 的后置处理
在 Bean 初始化之后,Spring 容器会调用所有注册的 BeanPostProcessor 的 postProcessAfterInitialization 方法,允许对 Bean 进行额外的处理。
- 常见用途:
-
- 生成代理对象(如 AOP 代理)。
- 执行一些后置逻辑。
9. Bean 可用
经过上述步骤后,Bean 已经初始化完成,可以被应用程序使用。
10. 销毁 Bean
当 Spring 容器关闭时,会销毁所有单例 Bean,并调用 Bean 的销毁方法。销毁的方式包括:
- 实现
DisposableBean接口:调用destroy()方法。 - 使用
@PreDestroy注解:标记销毁方法。 - XML 配置中的
destroy-method:指定销毁方法。
Bean 创建流程总结
- 加载 Bean 定义:通过配置文件或注解加载 Bean 的定义信息。
- 注册 BeanDefinition:将 Bean 的定义信息注册到
BeanFactory中。 - 实例化 Bean:通过反射创建 Bean 实例。
- 填充属性:通过依赖注入填充 Bean 的属性。
- 调用 Aware 接口:如果 Bean 实现了
Aware接口,注入相关上下文信息。 - BeanPostProcessor 前置处理:在初始化前对 Bean 进行处理。
- 初始化 Bean:调用初始化方法(如
afterPropertiesSet()、@PostConstruct)。 - BeanPostProcessor 后置处理:在初始化后对 Bean 进行处理。
- Bean 可用:Bean 初始化完成,可以被使用。
- 销毁 Bean:容器关闭时调用销毁方法。
代码示例
doGetBean{
1 从三级缓存获取bean getSingleton{
//依次singletonObjects,earlySingletonObjects,singletonFactories
1.1如果之前已经完整的创建过bean是从singletonObjects直接拿走
1.2如果循环依赖中先看earlySingletonObjects是否有,有的话直接返回。
1.3如果没有进入下面singletonFacotries拿出对象,拿到的实际是对象工厂,调用getObject把对象拿出来,拿出来之后需要进行aop的织入处理细节如下。
拿出来的对象要放到earlySingletonObjects供之后的调用使用
{
1.3.1拿到对象
1.3.2对象进行SmartInstantiationAwareBeanPostProcessor处理{
调用getEarlyBeanReference这个方法,这个方法实际的实现主要是做aop处理。找到所有的advisor,然后看当前的bean是否要织入对象,
如果织入的话,将对象代理。返回这个代理对象。
}
}
}
//上面三级缓存没拿到对象,那只能创建对象了
2创建对象createBean{
2.1resolveBeforeInstantiation处理InstantiationAwareBeanPostProcessor{
//这一步是想提前把bean创建出来然后直接返回,主要给aop留一个口子。创建出对象的话就直接结束了。
2.1.1处理InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation,为空的话就跳出
这一步有个问题AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation实际实现了aop的代理,为什么正常这里会返回空呢?以前一直以为代理从这里就结束了,实际我们平时使用的代理,这里都返回空并不会做aop。原因就是这个方法代理有个条件就是要设置CustomTargetSource属性,如果这个属性为空则不设置代理。平时自动代理的情况,这个属性都是null,所以此处并不会返回代理。
2.1.2然后如果返回不为空则继续InstantiationAwareBeanPostProcessor的postProcessorsAfterInitialization
2.1.3把刚才返回的对象直接返回了。创建对象结束。
}
//上面如果没有创建代理对象,那么这时候需要进行实际的对象创建。
2.2实际创建对象doCreateBean{
2.2.1 根据bean的定义创建对象,一般是用类反射出对象,这个根据创建对象的策略来处理createBeanInstance
//到这一步对象已经创建出来了。类似于我们做了new Object()。下面开始对每个属性赋值或者注入依赖对象
2.2.2 applyMergedBeanDefinitionPostProcessors处理MergedBeanDefinitionPostProcessor{
调用postProcessMergedBeanDefinition方法进行beanDefinition的处理。
//问题来了,对象都已经创建了 beandefinition还处理干嘛用呢,实际上这里会把@Autowire,@Value,@Resource,@Inject,@PostConstructor。。。等还有好多类似的注解的信息解析出来,并且作为beanDefinition的扩展属性信息,在后面设置属性的时候能够用到。
}
2.2.3 addSingletonFactory将刚创建的对象放到对象工厂中也就是上面三级缓存中的singletonFactories(这块使用看上面三级缓存)。
2.2.4 开始填充对象的属性populateBean{
2.2.4.1处理InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation对象已经实例化完了,这时候要触发这个after的回调postProcessAfterInstantiation
这中间漏了一步,是处理autowireMode。默认是NO不自动处理依赖注入。常用的有byname,bytype设置了之后,会扫描这个bean中的所有setxxx方法,把这个xxx认为是需要依赖注入的属性,
放到psv中后面设置这些值。mybatis扩展实现中就用到了这个。
2.2.4.2处理InstantiationAwareBeanPostProcessor的postProcessPropertyValues实际设置属性之前触发。这里扩展实现中会去处理@Autowire,@Value,@Resource,@Inject,@PostConstructor。。。等等注解的属性和方法,把这些属性对应的bean通过getBean从容器中获取出来,并且把bean的值注入给外层bean。这块详情如下
//以AutowiredAnnotationBeanPostProcessor为例,这个处理Autowired和Value和jsr的Inject,有另一个CommonAnnotationBeanPostProcessor会处理javax标准的注解Resource,PostConstruct,PreDestroy。这里主要有两步骤,第一先找到这个类中的所有注解的属性和方法,第二步把属性或方法对应的bean从工厂中获取出来完成注入。
{
2.2.4.2.1findAutowiringMetadata找到所有注入的属性和方法{
查找的方法主要是反射bean的属性和方法看看注解上是否有上面列出的注解,有的话就把注解里的属性构造成一个element对象收集起来放到列表中
}
2.2.4.2.2inject把这些属性从工厂中获取bean注入到对象中{
循环上面的element对象一个个的去完成获取bean注入到对象的操作。
//注意获取bean的时候又回到最外面dogetbean了,因此a依赖b,则b会先创建出来,然后注入到a里。就是这块完成的。
}
}
2.2.4.3上面把依赖注入的属性已经注入进去了,接着就处理其他普通的属性applyPropertyValues。
//处理属性的时候就会用到propertyEditorRegistry,propertyEditor根据属性的类型找到相应的propertyEditor,将属性值进行转换后设置。默认会把各种基本类型的propertyEditor放到propertyEditorRegistry里,自定义的也可以放到这里面来。所有的propertyEditor在这里都可以使用。
}
2.2.5initializeBean调用对象的初始化方法,比如afterPropertiesSet或者自定义的init,@PostConstruct等
{
2.2.5.1applyBeanPostProcessorsBeforeInitialization触发BeanPostProcessor的postProcessBeforeInitialization对象初始化之前的回调{
在容器中会有一个AnnotationAwareAspectJAutoProxyCreator此时会被调用,这个实现的是SmartInstantiationAwareBeanPostProcessor有getEarlyBeanReference也有postProcessBeforeInitialization,这两个方法做的事情类似都是把对象进行aop代理。此处调用的是postProcessBeforeInitialization,getEarlyBeanReference是在上面1.3.2步骤调用的。
}
2.2.5.2 invokeInitMethods调用初始化的方法{
如果有afterPropertiesSet则先调用,如果配置了其他init-method 则调用。这里就可以看到afterPropertiesSet是在initmethod前面调用的。
}
2.2.5.3 applyBeanPostProcessorsAfterInitialization触发BeanPostProcessor的postProcessAfterInitialization对象初始化之后的回调{
这个没有特殊处理。只是触发扩展
}
}
2.2.6getSingleton再次调用1三级缓存获取对象。前面调用过了为什么还要再调用一次,这个有各参数是否允许调用到第三级缓存的开关,此时是false所以这一步不会调用到singletonFacotries严格意义上只能算是取两级缓存。第三级缓存主要是处理循环依赖。比如A和B循环依赖,先找A,A注入B的时候开始getbean创建B,B在注入属性的时候又要找A,这时候A已经是可以走到上面1,从singletonFacotries拿出来,并且进行了aop代理,代理之后放到了earlySingletonObjects。这一步很重要,earlySingletonObjects里面存的是已经aop代理过的A。当B完成回到A的时候,A完成上面2.2.5,进入到2.2.6这时候就能从earlySingletonObjects把刚才B循环拿A的时候代理的A从这里拿走。并且返回。如果不这么做,返回回去的A是未代理的A
到这里bean就完全创建出来了。创建出来之后会放到singletonObjects。结束。
}
}
}



939

被折叠的 条评论
为什么被折叠?



