一、Spring简介
1. 概述
- Spring是一个轻量级Java开发框架(最早由Rod Johnson创建),为Java应用程序提供全面的基础架构支持。
- Spring最根本的使命是解决企业级应用开发的复杂性,简化Java开发。
2. Spring两个核心特性
① IoC(Inverse of Control)–> 控制反转
- IoC理念:
- 对象的创建工作交给IoC容器
- 对象间的依赖关系交给IoC容器查找,在运行期间确定
- 依赖注入是IoC的主要实现方式
- IoC的实现机制:
工厂模式 + 反射机制:工厂模式提供创建方法,通过反射获取需要加载的类的全限定名称,通过工厂加载产生需要的类对象。
② AoP(Aspect Oriented Programing) --> 面向切面编程
- AoP理念:通过预编译/运行时动态代理的方式,将那些与业务无关但对多个对象产生影响的公共行为(如日志、事务等),抽取并封装成可重用的模块 --> “切面”
- Spring中AoP提供声明式事务,允许用户自定义切面
二、IoC详解
1. 核心容器
- 容器提供了IoC功能,BeanFactory和ApplicationContext都是容器
容器类型 | 作用 | 加载方式 |
---|---|---|
BeanFactory | 低级容器:功能少 | 懒加载,用到实例才加载 |
ApplicationContext | 高级容器:功能多 | 预加载,容器启动时一次性加载 |
- 总结:
① ApplicationContext是BeanFactory的子接口,在基本功能之上提供了更多的功能:
- 继承了MessageSource,支持国际化
- 提供统一的资源访问方式
- 同时加载多个配置文件,可载入上下文(具有层级关系)
② BeanFactory为低级容器,类似于Map(Key --> BeanName,Value --> Bean实例),BeanFactory只提供最简单的注册(put)和获取(get)两个功能
③ ApplicationContext为高级容器,继承多个接口,功能强大
2. ApplicationContext常见实现
① FileSystemXmlApplicationContext:全路径名找Xml
② ClassPathXmlApplicationContext:在ClassPath中找Xml
③ WebXmlApplicationContext:一般从RequestContextUtils中获取Xml
3. DI(Dependency Injection)依赖注入
- DI依赖注入是IoC控制反转的重要实现方式
- 注入方式(3钟)
① Xml配置:
- 接口注入:灵活性差,易用性差,Spring4后弃用
- 构造器注入:全属性注入,任何改动会导致新实例的创建<constructor-arg name="" value=""/)
- Setter方法注入:部分/全属性注入,改动不会导致新实例的创建 <property name="" value=""/)
② 注解配置(将类对象托管给容器)
- @Component(“BeanName”) --> 可显示地指定BeanName,若不指定则按照类名驼峰命名
衍生出@Controller + @Service + @Repository/@Mapper- 在属性上方@Value可以直接对该属性赋值
③ Java配置
- @Configuration + @Bean
- @Bean在方法上使用,方法返回值作为JavaBean被托管到容器中
4. JavaBean作用域(Scope)
① SingleTon:单例模式(默认),每次返回的实例为同一个,适用于无状态的JavaBean
② ProtoType:原型模式,每次返回一个新的JavaBean,适用于有状态的JavaBean
③ Web应用中:
request:为每一个请求创建一个实例
session:同一个session会话共享一个实例,不同会话使用不同实例
global-session:全局作用域,所有session会话共享一个实例
5. Bean的装配机制
- ① Xml中显示装配(ref)
- ② Java代码中显示装配 @Configuration + @Bean
- ③ 自动装配
- 自动装配主要分为两种:byName和byType,可在xml中加入autowire=byName/byType来指定自动装配方法
- @Autowired自动装配:先按照byType装配,若对应type的对象有多个,则按照类名驼峰命名的名字进行byName装配
- @Qualifier(“BeanName”):指定具体JavaBean名,进行byName加载;主要是作为@Autowired的补充修饰,消除歧义
- @Resource:先按照byName进行装配,然后按照buType装配
6. Bean的生命周期
- 简单来说分为四个阶段:
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 销毁 Destruction
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5s08on6a-1626181763936)(http://182.92.190.128:8090/upload/2021/07/image-a4e39ff9b3a54e44828f6be6b7e39ca7.png)]
(1)实例化Bean:
- 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
- 对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。
(2)设置对象属性(依赖注入):
- 实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成属性设置与依赖注入。
(3) InitializingBean:
- 如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。
(4) destroy-method:
- 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
- 详细的生命周期形成过程在后面的源码解析中!
三、AoP详解
1. SpringAop名词解释
① 切面(Aspect):由通知 + 切点组成
② 连接点(Join Point):能够插入切面的点
③ 通知(Advice):切面的逻辑(工作内容)
④ 切点(PointCut):切点的定义用于匹配通知所要织入的连接点
⑤ 引入(Introduction)
⑥ 目标对象(Target):被切面通知的对象
⑦ 织入(Wearing):切面插入,创建新代理对象
2. 通知类型
- Before
- After
- Around
- AfterReturning
- AfterThrowing
3. SpringAoP 和 AspectJAoP
- AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表;而动态代理则以 Spring AOP 为代表
- Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理
类型 | 原理 | 织入对象 | 局限 |
---|---|---|---|
AspectJAoP | 静态代理增强,切面逻辑织入字节码 | 编译/类加载期间生成AoP代理类,织入颗粒度更细 | 性能更好,但需要特定编译器 |
JDK动态代理 | JDK动态代理,不修改字节码 | 为方法生成代理对象,方法级别的连接点 | 只能代理接口 |
Cglib动态代理 | 字节码生成,通过继承方式实现代理 | 运行时生成子类,覆盖特定方法并添加增强代码 | final类无法代理 |
- 注意:
- JDK动态代理只提供接口的代理,不支持类的代理,核心为InvocationHandler接口和Proxy类
- 如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类;
- CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的
四、Spring容器的启动流程
1. 总体流程
- 初始化Spring容器,注册内置的BeanPostProcessor的BeanDefinition到容器中
- 将配置类的BeanDefinition注册到容器中
- 调用refresh()方法刷新容器
- 调用构造方法,初始化容器:
- AnnotationConfigApplicationContext是注解注入
- ClassPathXmlApplicationContext 是xml注入
- 我们调用的是有参的构造方法,有参构造方法中会自动调用无参构造方法this()进行操作
- AnnotationConfigApplicationContext和ClassPathXmlApplicationContext 都继承自AbstractApplicationContext ,其中定义了refresh()方法
// 初始化容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this(); // 1. 注册 Spring 内置后置处理器的 BeanDefinition 到容器
register(annotatedClasses); // 2. 注册配置类 BeanDefinition 到容器
refresh(); // 3. 加载或者刷新容器中的Bean
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-samvvSU8-1626181763939)(http://182.92.190.128:8090/upload/2021/07/image-ff5602dda5ce4f70b56d6f22ed2ab112.png)]
2. 初始化流程
(1) 无参构造函数this()
- 主要完成以下三项工作
- 实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象
- 实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取转化成 BeanDefinition 对象,(BeanDefinition 是 Spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等)
- 实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象
// 无参构造方法
public AnnotationConfigApplicationContext() { // 实例化Spring容器
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this); // 实例化配置读取器
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this); // 实例化路径扫描器
}
(2) 内置组件添加
-
调用无参构造函数this()完成后,Spring容器已经构造完毕,这时需要为容器添加一些内置组件
-
调用方法:org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors
-
主要组件:
- ConfigurationClassPostProcessor:beanFactory后置处理器,用来完成 bean 的扫描与注入工作
- AutowiredAnnotationBeanPostProcessor:bean后置处理器,用来完成 @AutoWired 自动注入
-
源码跟踪:
- 容器有参构造 --> this()无参
- new AnnotatedBeanDefinitionReader(this) --> 构造方法中调用
- AnnotationConfigUtils --> registerAnnotationConfigProcessors() 方法添加内置组件
-
构造方法源码:渐进调用
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); // 内置组件添加
}
- 内置组件添加源码:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 向beanDefinitionMap中注册BeanFactoryProcessor:ConfigurationClassPostProcessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 向beanDefinitionMap中注册BeanPostProcessor:AutowiredAnnotationBeanPostProcessor
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
// 向beanDefinitionMap中注册BeanPostProcessor:CommonAnnotationBeanPostProcessor
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
// 向beanDefinitionMap中注册BeanPostProcessor:PersistenceAnnotationBeanPostProcessor
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
(3) 注册SpringConfig配置类到容器中
-
源码跟踪
- 容器初始化构造方法中的register(componentClasses)方法
- 调用this.reader.register(componentClasses)
- registerBean(componentClass) --> doRegisterBean(beanClass , …)
-
doRegisterBean源码分析:
-
- 解析用户传入的Spring配置类
-
- 将配置类封装成一个BeanDefinition注册到容器中
-
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
(4) refresh()容器刷新
-
源码跟踪:
- refresh()方法在AbstractApplicationContext这个抽象父类中
-
refresh源码分析:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 刷新前的预处理
prepareRefresh();
// 2. 获取 beanFactory,即前面创建的【DefaultListableBeanFactory】
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 预处理 beanFactory,向容器中添加一些组件
prepareBeanFactory(beanFactory);
try {
// 4. 子类通过重写这个方法可以在 BeanFactory 创建并与准备完成以后做进一步的设置
postProcessBeanFactory(beanFactory);
// 5. 执行 BeanFactoryPostProcessor 方法,beanFactory 后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessors,bean 后置处理器
registerBeanPostProcessors(beanFactory);
// 7. 初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析)
initMessageSource();
// 8. 初始化事件派发器,在注册监听器时会用到
initApplicationEventMulticaster();
// 9. 留给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑,web 场景下会使用
onRefresh();
// 10. 注册监听器,派发之前步骤产生的一些事件(可能没有)
registerListeners();
// 11. 初始化所有的非单实例 bean
finishBeanFactoryInitialization(beanFactory);
// 12. 发布容器刷新完成事件
finishRefresh();
}
...
}
}
- refresh()功能:refresh()部分源码详解
1. prepareRefresh()刷新前的预处理:
(1)initPropertySources():初始化一些属性设置,子类自定义个性化的属性设置方法;
(2)getEnvironment().validateRequiredProperties():检验属性的合法性
(3)earlyApplicationEvents = new LinkedHashSet():保存容器中的一些早期的事件;
2. obtainFreshBeanFactory():获取在容器初始化时创建的BeanFactory:
(1)refreshBeanFactory():刷新BeanFactory,设置序列化ID;
(2)getBeanFactory():返回初始化中的GenericApplicationContext创建的BeanFactory对象,即【DefaultListableBeanFactory】类型
3. prepareBeanFactory(beanFactory):BeanFactory的预处理工作,向容器中添加一些组件:
(1)设置BeanFactory的类加载器、设置表达式解析器等等
(2)添加BeanPostProcessor【ApplicationContextAwareProcessor】
(3)设置忽略自动装配的接口:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware;
(4)注册可以解析的自动装配类,即可以在任意组件中通过注解自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
(5)添加BeanPostProcessor【ApplicationListenerDetector】
(6)添加编译时的AspectJ;
(7)给BeanFactory中注册的3个组件:environment【ConfigurableEnvironment】、systemProperties【Map<String, Object>】、systemEnvironment【Map<String, Object>】
4. postProcessBeanFactory(beanFactory):子类重写该方法,可以实现在BeanFactory创建并预处理完成以后做进一步的设置
5. invokeBeanFactoryPostProcessors(beanFactory):在BeanFactory标准初始化之后执行BeanFactoryPostProcessor的方法,即BeanFactory的后置处理器
(1)先执行BeanDefinitionRegistryPostProcessor: postProcessor.postProcessBeanDefinitionRegistry(registry)
- ① 获取所有的实现了BeanDefinitionRegistryPostProcessor接口类型的集合
② 先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor
③ 再执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor
④ 最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors
(2)再执行BeanFactoryPostProcessor的方法:postProcessor.postProcessBeanFactory(beanFactory)
- ① 获取所有的实现了BeanFactoryPostProcessor接口类型的集合
② 先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor
③ 再执行实现了Ordered顺序接口的BeanFactoryPostProcessor
④ 最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor
6. registerBeanPostProcessors(beanFactory):向容器中注册Bean的后置处理器BeanPostProcessor,它的主要作用是干预Spring初始化bean的流程,从而完成代理、自动注入、循环依赖等功能
(1)获取所有实现了BeanPostProcessor接口类型的集合:
(2)先注册实现了PriorityOrdered优先级接口的BeanPostProcessor;
(3)再注册实现了Ordered优先级接口的BeanPostProcessor;
(4)最后注册没有实现任何优先级接口的BeanPostProcessor;
(5)最refresh主要可划分为12个步骤,其中比较重要的步骤下面会有详细说明。Spring 中的每一个容器都会调用 refresh() 方法进行刷新,无论是 Spring 的父子容器,还是 Spring Cloud Feign 中的 feign 隔离容器,每一个容器都会调用这个方法完成初始化。终注册MergedBeanDefinitionPostProcessor类型的BeanPostProcessor:beanFactory.addBeanPostProcessor(postProcessor);
(6)给容器注册一个ApplicationListenerDetector:用于在Bean创建完成后检查是否是ApplicationListener,如果是,就把Bean放到容器中保存起来:applicationContext.addApplicationListener((ApplicationListener<?>) bean);
此时容器中默认有6个默认的BeanProcessor(无任何代理模式下):【ApplicationContextAwareProcessor】、【ConfigurationClassPostProcessorsAwareBeanPostProcessor】、【PostProcessorRegistrationDelegate】、【CommonAnnotationBeanPostProcessor】、【AutowiredAnnotationBeanPostProcessor】、【ApplicationListenerDetector】
7. initMessageSource():初始化MessageSource组件,主要用于做国际化功能,消息绑定与消息解析:
(1)看BeanFactory容器中是否有id为messageSource 并且类型是MessageSource的组件:如果有,直接赋值给messageSource;如果没有,则创建一个DelegatingMessageSource;
(2)把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource;
8. initApplicationEventMulticaster():初始化事件派发器,在注册监听器时会用到
(1)看BeanFactory容器中是否存在自定义的ApplicationEventMulticaster:如果有,直接从容器中获取;如果没有,则创建一个SimpleApplicationEventMulticaster
(2)将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件就可以直接自动注入
9. onRefresh():留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑
10. registerListeners():注册监听器:将容器中所有的ApplicationListener注册到事件派发器中,并派发之前步骤产生的事件:
(1)从容器中拿到所有的ApplicationListener
(2)将每个监听器添加到事件派发器中:getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
(3)派发之前步骤产生的事件applicationEvents:getApplicationEventMulticaster().multicastEvent(earlyEvent);
11. finishBeanFactoryInitialization(beanFactory):初始化所有剩下的单实例bean,核心方法是preInstantiateSingletons(),会调用getBean()方法创建对象
(1)获取容器中的所有beanDefinitionName,依次进行初始化和创建对象
(2)获取Bean的定义信息RootBeanDefinition,它表示自己的BeanDefinition和可能存在父类的BeanDefinition合并后的对象
(3)如果Bean满足这三个条件:非抽象的,单实例,非懒加载,则执行单例Bean创建流程:
(4)所有Bean都利用getBean()创建完成以后,检查所有的Bean是否为SmartInitializingSingleton接口的,如果是;就执行afterSingletonsInstantiated()
12.finishRefresh():发布BeanFactory容器刷新完成事件
1)initLifecycleProcessor():初始化和生命周期有关的后置处理器:默认从容器中找是否有lifecycleProcessor的组件【LifecycleProcessor】,如果没有,则创建一个DefaultLifecycleProcessor()加入到容器;
(2)getLifecycleProcessor().onRefresh():拿到前面定义的生命周期处理器(LifecycleProcessor)回调onRefresh()方法
(3)publishEvent(new ContextRefreshedEvent(this)):发布容器刷新完成事件;
(4)liveBeansView.registerApplicationContext(this);
五、Spring中Bean的加载流程
1. 容器启动阶段
-
容器的启动阶段做了很多的预热工作,为后面Bean的实例化做好了充分的准备,主要工作有以下5步
-
转载自:Spring中Bean的加载流程
1. 配置元信息:
- Spring IOC容器将对象实例的创建与对象实例的使用分离,当业务中需要依赖某个对象,不再依靠我们自己手动创建,只需向Spring要,Spring就会以注入的方式交给我们需要的依赖对象。既然将对象创建的任务交给了Spring,那么Spring就需要知道创建一个对象所需要的一些必要的信息。而这些必要的信息可以是Spring过去支持最完善的xml配置文件,或者是其他形式的例如properties的磁盘文件,也可以是现在主流的注解,甚至是直接的代码硬编码。总之,这些创建对象所需要的必要信息称为配置元信息。
2. BeanDefination:
- 在Java世界中,万物皆对象,散落于程序代码各处的注解以及保存在磁盘上的xml或者其他文件等等配置元信息,在内存中总要以一种对象的形式表示,就好比我们活生生的人对应到Java世界中就是一个Person类,而Spring选择在内存中表示这些配置元信息的方式就是BeanDefination,这里我们不会去分析BeanDefination的代码,这里我们只需要知道配置元信息被加载到内存之后是以BeanDefination的形存在的即可。
3. BeanDefinationReader:
- Spring是如何看懂这些配置元信息的呢?这个就要靠我们的BeanDefinationReader了。不同的BeanDefinationReader拥有不同的功能,如果我们要读取xml配置元信息,那么可以使用XmlBeanDefinationReader。如果我们要读取properties配置文件,那么可以使用PropertiesBeanDefinitionReader加载。而如果我们要读取注解配置元信息,那么可以使用 AnnotatedBeanDefinitionReader加载。我们也可以很方便的自定义BeanDefinationReader来自己控制配置元信息的加载。总的来说,BeanDefinationReader的作用就是加载配置元信息,并将其转化为内存形式的BeanDefination,存在某一个地方,至于这个地方在哪里,不要着急,接着往下看!
4. BeanDefinationRegistry:
- 执行到这里,Spring已经将存在于各处的配置元信息加载到内存,并转化为BeanDefination的形式,这样我们需要创建某一个对象实例的时候,找到相应的BeanDefination然后创建对象即可。那么我们需要某一个对象的时候,去哪里找到对应的BeanDefination呢?这种通过Bean定义的id找到对象的BeanDefination的对应关系或者说映射关系又是如何保存的呢?这就引出了BeanDefinationRegistry了。
- Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。
5. BeanFactoryPostProcessor:
- BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。例如我们的配置元信息中有些可能会修改的配置信息散落到各处,不够灵活,修改相应配置的时候比较麻烦,这时我们可以使用占位符的方式来配置。例如配置Jdbc的DataSource连接的时候可以这样配置:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="maxIdle" value="${jdbc.maxIdle}"></property>
<property name="maxActive" value="${jdbc.maxActive}"></property>
<property name="maxWait" value="${jdbc.maxWait}"></property>
<property name="minIdle" value="${jdbc.minIdle}"></property>
<property name="driverClassName"
value="${jdbc.driverClassName}">
</property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
- BeanFactoryPostProcessor就会对注册到BeanDefinationRegistry中的BeanDefination做最后的修改,替换$占位符为配置文件中的真实的数据。
2. Bean获取阶段
- 在容器启动阶段,所有Bean的注册已经完成,接下来通过懒加载/预加载两种方式实例化Bean对象
- 懒加载:
Spring只有在第一次依赖对象时才开启相应的实例化阶 - 预加载:
容器启动阶段完成之后,其中有一个步骤finishBeanFactoryInitialization(),在这一步将立即启动Bean实例化阶段,通过隐式调用所有依赖对象的getBean()方法来实例化所有配置的Bean,完成类的加载。
- 懒加载:
(1) Bean的获取(实例化):doGetBean()
doGetBean()的总体功能就是在创建bean对象之前,先去缓存或者beanFactory工厂中查看是否存在bean,如果存在,则返回,不存在,则进行对应的创建流程。
- 源码阅读:
① 首先调用 ApplicationContext.getBean(“beanName”)获取Bean对象:
applicationContext.getBean("name");
② 然后再调用AbstractApplicationContext.getBean(“beanName”):
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
// 调用getBean 进入AbstractBeanFactory
return getBeanFactory().getBean(name);
}
③ 再调用AbstractBeanFactory类下面的doGetBean()方法:
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
/*
1、转换beanName(别名转换):传入的参数name可能只是别名,也可能是FactoryBean,所以需要进行解析转换:
(1)消除修饰符,比如工厂引用前缀 String FACTORY_BEAN_PREFIX = "&";
(2)解决spring中alias标签的别名问题
*/
final String beanName = transformedBeanName(name);
Object bean;
//2、尝试从缓存中去加载实例,如果获取到了就直接返回
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//如果缓存中存在对应的bean
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//3、缓存渠道的bean的实例化。从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化。
// 此时会进行 合并RootBeanDefinition、BeanPostProcessor进行实例前置处理、实例化、实例后置处理。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 如果缓存中没有对应bean
else {
//4、循环依赖检查。 (构造器的循环依赖)循环依赖存在,则报错。
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 5、如果缓存中没有数据,就会转到父类工厂去加载
//获取父工厂
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
//!containsBeanDefinition(beanName)就是检测如果当前加载的xml配置文件中不包含beanName所对应的配置,就只能到parentBeanFacotory去尝试加载bean。
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
//6、存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。
try {
// XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但Bean的后续处理是针对于RootBeanDefinition的,所以需要转换后才能进行后续操作。
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//7、初始化依赖的bean
String[] dependsOn = mbd.getDependsOn();
//bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
//8、创建bean
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
(2) 从缓存中获取单例Bean:getSingleton()
- 在doGetBean()方法中,获取Bean首先会在缓存中查找对应的单例Bean是否存在
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从缓存池中获取bean:singletonObjects 一级缓
Object singletonObject = this.singletonObjects.get(beanName);
// 如果一级缓存中为null,再判断是否正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加锁,防止并发创建
synchronized (this.singletonObjects) {
// 从二级缓存中获取bean,如果此 bean 正在加载则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 当某些方法需要提前初始化,调用 addSingletonFactory 方法将对应的objectFactory 初始化策略存储在 singletonFactories
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
- 在 Spring 中,bean默认都是单例的,同一个容器的单例只会被创建一次,后续再获取 bean 时,直接从单例缓存 singletonObjects 中进行获取。而且因为单例缓存是公共变量,所以对它进行操作的时候,都进行了加锁操作,避免了多线程并发修改或读取的覆盖操作。
- 还有这里有个 earlySingletonObjects 变量,它也是单例缓存,也是用来保存 beanName 和 创建 bean 实例之间的关系。与 singletonFactories 不同的是,当一个单例 bean 被放入到这 early 单例缓存后,就要从 singletonFactories 中移除,两者是互斥的,主要用来解决循环依赖的问题。
(3) 从实例Bean中获取对象:getObjectForBeanInstance()
- 在 getBean()/doGetBean()方法中,getObjectForBeanInstance() 是个高频方法,在单例缓存中获得 bean 还是 根据不同的 scope 策略加载 bean,都有这个这个方法的出现。因为从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance; // 如果是nullBean
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); // 如果不是工厂Bean也不是空Bean,报错
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null; // 加载工厂Bean
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName); // 先从缓存中获取
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // 通过工厂getObject方法实例化Bean
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName); // 尝试从单例缓存中获取
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic); // 用户自定义工厂Bean
}
return object;
}
方法功能总结:
(1)验证 bean 类型:判断是否是工厂bean
(2)对非 FactoryBean 不做处理
(3)处理 FactoryBean:如果是FactoryBean类型,先对 bean 进行转换,再委托给 getObjectFromFactoryBean()方法进行处理。
在这个方法中,对工厂 bean 有特殊处理,最终获取的是 FactoryBean.getObject() 方法返回的类型。
(4) 加载单例Bean:getSingleton()
- 源码:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 注释 4.7 全局变量,加锁
synchronized (this.singletonObjects) {
//1、再次检查是否已经被加载了,单例模式就是可以复用已经创建的 bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//2、初始化前操作,校验是否 beanName 是否有别的线程在初始化,并记录beanName的初始化状态
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
//3、调用createBean方法实例化bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//4、初始化后的操作,移除初始化状态
afterSingletonCreation(beanName);
if (newSingleton) {
//5、加入缓存
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
功能总结:
(1)再次检查缓存是否已经加载过
(2)没有加载,则记录beanName 的加载状态
(3)调用createBean()方法实例化 bean
(4)bean实例化完成之后,移除初始化状态
(5)将实例化结果记录到缓存并删除加载 bean 过程中所记录到的各种辅助状态
- 对于第(2)步和第(4)步,用来记录 bean 的加载状态,是用来对循环依赖进行检测的。关键的方法createBean(),调用了 ObjectFactory 的 getObject() 方法,实际回调接口实现的是 createBean() 方法进行创建对象(在doGetBean()中)。
3. Bean的实例化阶段:(真正创建对象)
- 实例化Bean的方法为createBean(),在其中再调用doCreateBean()
(1) createBean()
主要流程:
(1)根据设置的 class 属性或者根据 className 来解析 Class --> resolveBeanClass()
(2)验证及准备覆盖的方法 --> prepareMethodOverrides():这个方法是用来处理以下两个配置的:我们在解析默认标签时,会识别 lookup-method 和 replaced-method 属性,然后这两个配置的加载将会统一存放在 beanDefinition 中的 methodOverrides 属性里。
(3)应用初始化前的后处理器,解析指定 bean 是否存在初始化前的短路操作
(4)创建 bean --> doCreateBean()
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// 保证bean已经被解析,并且克隆bean定义
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides. 验证/准备方法覆盖
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 指定解析Bean,让beanPostProcessor有机会返回代理而不是bean实例
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) { // 短路操作,如果代理成功创建Bean,则直接返回
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 创建Bean实例:doCreateBean()
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
(2) prepareMethodOverrides()
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exist and determine their overloaded status.
if (hasMethodOverrides()) {
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
// 上述循环中调用
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false);
}
}
可以看到,获取类的重载方法列表,然后遍历,一个一个进行处理。具体处理的是 lookup-method 和 replaced-method 属性,这个步骤解析的配置将会存入 beanDefinition 中的 methodOverrides 属性里,是为了待会实例化做准备。 如果 bean 在实例化时,监测到 methodOverrides 属性,会动态地位当前 bean 生成代理,使用对应的拦截器为 bean 做增强处理。
(3) resolveBeforeInstantiation()
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 前置拦截器操作
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 后置拦截器操作
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
在 doCreateBean() 方法前,有一个短路操作,如果后处理器成功,将会返回代理的 bean。
在 resolveBeforeInstantiation() 方法中,在确保 bean 信息已经被解析完成之后,执行了两个关键方法,从注释中看到,一个是前置拦截器的操作,另一个就是后置拦截器的操作。
如果第一个前置拦截器实例化成功,就已经将单例 bean 放入缓存中,它不会再经历普通 bean 的创建过程,没有机会进行后处理器的调用,所以在这里的第二个步骤,就是为了这个 bean 也能应用后处理器的 postProcessAfterInitialization 方法。而如果这个bean没有特定的前置处理,那说明这个bean是一个普通的bean,则按照下面的步骤进行创建
(4) doCreateBean()
整体流程
(1)如果要加载的bean是单例,就先清除缓存中的bean信息
(2)实例化 bean,将 BeanDifinition 转化成 BeanWrapper
(3)后置处理器修改合并后的 bean 定义:bean 合并后的处理,Autowired 注解正式通过此方法实现诸如类型的预解析
(4)依赖处理,提前暴露bean的引用,主要用于解决循环依赖的问题
(5)属性填充:将所有属性填充到 bean 的实例中,如果存在对其他bean的依赖,将会递归初始化依赖的bean
(6)初始化bean:例如afeterPropertiesSet()和init-method属性配置的方法
(7)循环依赖检查
(8)注册 DisposableBean:这一步是用来处理 destroy-method 属性,在这一步注册,以便在销毁对象时调用。
(9)完成创建并返回。
详解:Bean初始化详解