深入了解Spring
Bean
Java bean和spring bean区别
- Java bean的属性私有,只能通过get和set方法来对属性进行操作。
- Spring bean是由spring容器生成和管理的对象。
spring Bean的定义方式
-
xml文件 。 声明式。
-
@bean注解。 声明式。
-
@component注解。声明式。
-
@BeanDefinition。编程式
-
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); beanDefinition.setBeanClass(User.class); annotationConfigApplicationContext.registerBeanDefinition("user",beanDefinition); annotationConfigApplicationContext.refresh(); //取出 User user=annotationConfigApplicationContext.getBean("user",User.class);
-
-
实现FactoryBean接口
-
自定义工厂类
public class ZhuFactoryBean implements FactoryBean { //获取对象 public Object getObject() throws Exception { Person person=new Person(); return person; } //获取类型 public Class<?> getObjectType() { return Person.class; } public boolean isSingleton() { return false; } }
-
定义bean和取出bean
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); beanDefinition.setBeanClass(ZhuFactoryBean.class); //注册工厂类会将工厂类本身添加进入容器,也会将工厂添加的bean注入容器 annotationConfigApplicationContext.registerBeanDefinition("person",beanDefinition); annotationConfigApplicationContext.refresh(); //取出工厂类 ZhuFactoryBean zhuFactoryBean=annotationConfigApplicationContext.getBean("&person",ZhuFactoryBean.class); //取出工厂定义的bean Person person=annotationConfigApplicationContext.getBean("person",Person.class); System.out.println(zhuFactoryBean); System.out.println(person);
-
-
使用supplier定义bean
-
annotationConfigApplicationContext.registerBean(User.class, new Supplier<User>() { @Override public User get() { User user=new User(); user.setAge(11); return user; } });
-
spring容器
单例池
- spring中单例池存放的是单例bean,内部数据结构为concurrentHashMap,spring源码中的定义为Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256)。map的key为name,value为bean对象。它用于保存非懒加载的单例Bean。如果对象使用了AOP完成了一些操作,那么放入单例池的就是代理对象而不是他本身。
Bean生命周期
思维导图
- 简单来说:
流程总结
通过BeanDefinitionReader接口将xml或者注解配置的对象转换成BeanFactory中的beanDefinitionMap中的beanDefination。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ldqJlZOb-1685347461590)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114056465.png)]**—>
之后beanFactoryPostProcessor接口的postprocessorFactoryBean方法可以获取到对factoryBean的信息,也就能对beanDefination进行一些操作,例如对xml文件中的占位符进行拼接、对注解的扫描(例如@component修饰的类转化为一个beanDefinition对象)。
—–>**创建对象,过程可以分为下图两步。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YsWWdlRu-1685347461591)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210717191046208.png)]
spring在实例化的时候是采用反射的方式实例化对象的,之后填充属性。**—->**调用Aware接口中的方法(
Aware接口可以帮助自定义对象获取容器类对象(ApplicationContext、BeanFactory等),如简单对象通过实现ApplicationContextAware接口,可以让这个对象get到ApplicationContext容器
)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eZvWHet-1685347461592)(C:\Users\Ric\AppData\Local\Temp\企业微信截图_16265793448073.png)]
**—->**在bean创建之前调用before方法,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PYejt2Df-1685347461592)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112814382.png)]之后调用init方法,之后调用after方法(通过beanPostProcessor接口实现AOP,接口的实现类会创建代理对象)。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G87HYqDS-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112925284.png)]
**—-》**之后就是一个完整的bean对象了。
思维导图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLy6FkuI-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114858308.png)]
debug spring源码
debug入口
源码地址:https://gitee.com/qurywu/spring_study.git
使用注解的方式创建bean对象,以及取出bean
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = annotationConfigApplicationContext.getBean(User.class);
user.run();
初始化IOC
创建AnnotationConfigApplicationContext对象和核心方法
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
//step1
this();
//step2
this.register(componentClasses);
//step3
this.refresh();
}
step1:this()
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
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, (ResourceLoader)null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
这段代码是一个构造函数,用于创建一个AnnotatedBeanDefinitionReader对象。AnnotatedBeanDefinitionReader是一个用于读取注解的BeanDefinition的类,它的作用是将注解转换为BeanDefinition对象并注册到BeanDefinitionRegistry中。
在构造函数中,首先设置了beanNameGenerator和scopeMetadataResolver的值,分别用于生成Bean的名称和解析Bean的作用域。然后通过断言确保传入的BeanDefinitionRegistry和Environment对象不为空,接着将它们赋值给成员变量registry和conditionEvaluator。
最后,调用AnnotationConfigUtils.registerAnnotationConfigProcessors方法,该方法会注册一些用于处理注解的BeanPostProcessor,例如AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor等。
step2:this.register(componentClasses)
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())) {
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
//如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
这段代码是一个私有方法,用于注册一个BeanDefinition。该方法接收一个beanClass参数,表示要注册的Bean的类型;一个name参数,表示Bean的名称;一个qualifiers参数,表示Bean的限定符;一个supplier参数,表示Bean的实例提供者;一个customizers参数,表示BeanDefinition的自定义器。
在方法中,首先创建一个AnnotatedGenericBeanDefinition对象,并通过conditionEvaluator判断是否应该跳过该BeanDefinition。然后设置BeanDefinition的实例提供者和作用域,并根据传入的name或使用beanNameGenerator生成Bean的名称。接着调用AnnotationConfigUtils.processCommonDefinitionAnnotations方法处理BeanDefinition上的常见注解。
如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。如果传入了customizers参数,则遍历customizers数组,调用每个BeanDefinitionCustomizer的customize方法对BeanDefinition进行自定义。
最后,将BeanDefinition封装为BeanDefinitionHolder对象,并根据作用域设置代理模式,最终通过BeanDefinitionReaderUtils.registerBeanDefinition方法将BeanDefinition注册到BeanDefinitionRegistry中。
register的实质是注册到BeanDefinitionMap中
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
//beanDefinition校验
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
//通过那么从beanDefinitionMap中拿到BeanDefinition
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
//判断BeanDefinitionRegistry中是否已经存在同名的BeanDefinition对象。如果存在,则根据isAllowBeanDefinitionOverriding方法的返回值决定是否允许覆盖原有的BeanDefinition对象。如果允许覆盖,则根据BeanDefinition对象的角色和内容进行判断,如果需要覆盖则进行覆盖操作,否则不进行任何操作。
if (existingDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
//如果不存在同名的BeanDefinition对象,则将BeanDefinition对象添加到BeanDefinitionRegistry中,并更新BeanDefinitionRegistry中的Bean名称列表。如果BeanDefinitionRegistry已经开始创建Bean,则需要进行同步操作
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
this.removeManualSingletonName(beanName);
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition == null && !this.containsSingleton(beanName)) {
//如果BeanDefinitionRegistry中不存在同名的单例Bean,则清除缓存。
if (this.isConfigurationFrozen()) {
this.clearByTypeCache();
}
} else {
this.resetBeanDefinition(beanName);
}
}
这段代码是BeanDefinitionRegistry接口的默认实现,用于将BeanDefinition对象注册到BeanDefinitionRegistry中。该方法接收两个参数,一个是Bean的名称,另一个是BeanDefinition对象。
在方法中,首先通过断言确保传入的Bean名称和BeanDefinition对象不为空。如果BeanDefinition对象是AbstractBeanDefinition的实例,则调用validate方法进行验证,如果验证失败则抛出BeanDefinitionStoreException异常。
接着判断BeanDefinitionRegistry中是否已经存在同名的BeanDefinition对象。如果存在,则根据isAllowBeanDefinitionOverriding方法的返回值决定是否允许覆盖原有的BeanDefinition对象。如果允许覆盖,则根据BeanDefinition对象的角色和内容进行判断,如果需要覆盖则进行覆盖操作,否则不进行任何操作。如果不允许覆盖,则抛出BeanDefinitionOverrideException异常。
如果不存在同名的BeanDefinition对象,则将BeanDefinition对象添加到BeanDefinitionRegistry中,并更新BeanDefinitionRegistry中的Bean名称列表。如果BeanDefinitionRegistry已经开始创建Bean,则需要进行同步操作。最后,如果BeanDefinitionRegistry中不存在同名的单例Bean,则清除缓存。
step3:refresh(核心)
调用finishRefresh()方法,完成应用程序上下文的刷新。public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
//启动应用程序的启动步骤,记录“spring.context.refresh”步骤的开始时间。
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//调用prepareRefresh()方法,准备应用程序上下文的刷新。
this.prepareRefresh();
//调用obtainFreshBeanFactory()方法,获取一个新的bean工厂实例。
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//调用prepareBeanFactory()方法,对bean工厂进行一些准备工作,例如设置类加载器、添加属性编辑器等。
this.prepareBeanFactory(beanFactory);
try {
//调用postProcessBeanFactory()方法,对bean工厂进行后置处理,例如添加BeanFactoryPostProcessor等
this.postProcessBeanFactory(beanFactory);
//启动应用程序的启动步骤,记录“spring.context.beans.post-process”步骤的开始时间。
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
//调用invokeBeanFactoryPostProcessors()方法,调用所有注册的BeanFactoryPostProcessor的postProcessBeanFactory()方法。
this.invokeBeanFactoryPostProcessors(beanFactory);
//调用registerBeanPostProcessors()方法,注册所有BeanPostProcessor实例。
this.registerBeanPostProcessors(beanFactory);
// 结束“spring.context.beans.post-process”步骤。
beanPostProcess.end();
//调用initMessageSource()方法,初始化MessageSource实例。
this.initMessageSource();
//调用initApplicationEventMulticaster()方法,初始化ApplicationEventMulticaster实例。
this.initApplicationEventMulticaster();
//调用onRefresh()方法,执行应用程序上下文的自定义刷新逻辑。
this.onRefresh();
//调用registerListeners()方法,注册所有ApplicationListener实例。
this.registerListeners();
//调用finishBeanFactoryInitialization()方法,完成所有bean的实例化和初始化。
this.finishBeanFactoryInitialization(beanFactory);
//调用finishRefresh()方法,完成应用程序上下文的刷新。
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
这段代码是Spring框架中的ApplicationContext接口的refresh()方法的实现。该方法用于刷新应用程序上下文,即重新加载所有bean定义并重新实例化所有单例bean。
具体来说,该方法的实现包括以下步骤:
- 获取启动和关闭监视器的锁,确保线程安全。
- 启动应用程序的启动步骤,记录“spring.context.refresh”步骤的开始时间。
- 调用prepareRefresh()方法,准备应用程序上下文的刷新。
- 调用obtainFreshBeanFactory()方法,获取一个新的bean工厂实例。
- 调用prepareBeanFactory()方法,对bean工厂进行一些准备工作,例如设置类加载器、添加属性编辑器等。
- 调用postProcessBeanFactory()方法,对bean工厂进行后置处理,例如添加BeanFactoryPostProcessor等。
- 启动应用程序的启动步骤,记录“spring.context.beans.post-process”步骤的开始时间。
- 调用invokeBeanFactoryPostProcessors()方法,调用所有注册的BeanFactoryPostProcessor的postProcessBeanFactory()方法。
- 调用registerBeanPostProcessors()方法,注册所有BeanPostProcessor实例。
- 结束“spring.context.beans.post-process”步骤。
- 调用initMessageSource()方法,初始化MessageSource实例。
- 调用initApplicationEventMulticaster()方法,初始化ApplicationEventMulticaster实例。
- 调用onRefresh()方法,执行应用程序上下文的自定义刷新逻辑。
- 调用registerListeners()方法,注册所有ApplicationListener实例。
- 调用finishBeanFactoryInitialization()方法,完成所有bean的实例化和初始化。
- 调用finishRefresh()方法,完成应用程序上下文的刷新。
- 如果在刷新过程中发生异常,记录警告日志,销毁所有bean实例,取消刷新并抛出异常。
- 重置所有公共缓存。
- 结束“spring.context.refresh”步骤。
refresh方法的理解
-
refresh方法一共包含十三个子方法
-
prepareRefresh方法,负责容器刷新前的准备工作,如:如设置容器启动时间,容器活跃状态、获取environment对象、准备监听器和事件的集合对象。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C4hQlEnS-1685347461594)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719154130999.png)]
这段代码是Spring框架中的一个方法,用于准备应用程序上下文的刷新。下面是对代码的详细解读和优化建议:
-
第一行代码
this.startupDate = System.currentTimeMillis();
用于记录应用程序上下文启动的时间,可以用于性能分析和调试。没有优化建议。 -
第二行代码
this.closed.set(false);
用于将应用程序上下文的关闭状态设置为false,表示应用程序上下文没有关闭。没有优化建议。 -
第三行代码
this.active.set(true);
用于将应用程序上下文的活动状态设置为true,表示应用程序上下文正在运行。没有优化建议。 -
第四行代码
if (this.logger.isDebugEnabled()) {...}
用于判断日志级别是否为DEBUG,如果是,则记录“Refreshing”和应用程序上下文的名称或者对象。优化建议:可以将日志级别设置为INFO或WARN,避免在生产环境中记录过多的DEBUG级别日志。 -
第五行代码
this.initPropertySources();
用于初始化应用程序上下文的属性源,可以用于加载配置文件和环境变量等。优化建议:可以使用更高效的方式加载配置文件,例如使用Spring Cloud Config Server或者使用本地缓存等。 -
第六行代码
this.getEnvironment().validateRequiredProperties();
用于验证必需的属性是否已经设置,如果没有设置,则抛出异常。优化建议:可以使用更灵活的方式验证属性,例如使用Spring Boot的@ConfigurationProperties注解。 -
第七行代码
if (this.earlyApplicationListeners == null) {...}
用于初始化应用程序上下文的应用程序监听器,可以用于处理应用程序上下文的事件。优化建议:可以使用更高效的方式处理事件,例如使用异步事件处理器或者使用Spring Cloud Bus等。 -
第八行代码
this.earlyApplicationEvents = new LinkedHashSet();
用于初始化应用程序上下文的应用程序事件,可以用于记录应用程序上下文的事件。没有优化建议。
-
第一行代码
-
-
obtainFreshBeanFactory方法,创建Bean工厂,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpBkYE8n-1685347461595)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719154817721.png)]
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { this.refreshBeanFactory(); return this.getBeanFactory(); }
这段代码是Spring框架中的一个方法,用于刷新应用程序上下文的Bean工厂。下面是对代码的详细解读: 1. 方法签名 方法签名表明该方法是一个final方法,不能被子类重写。该方法没有参数,抛出IllegalStateException异常。 1. 方法实现 该方法首先检查refreshed属性的值,如果为true,则抛出IllegalStateException异常,表示不支持多次刷新。否则,将refreshed属性设置为true,并将Bean工厂的序列化ID设置为应用程序上下文的ID
将Bean工厂的序列化ID设置为应用程序上下文的ID有什么用?
在Java中,序列化是将对象转换为字节流的过程,以便在网络上传输或将其保存到磁盘上。在反序列化时,可以将字节流转换回对象。在序列化和反序列化过程中,Java使用一个称为序列化ID的标识符来标识对象的版本。如果序列化ID不匹配,则反序列化过程将失败。
在Bean工厂中,如果将序列化ID设置为应用程序上下文的ID,可以确保在反序列化时,Bean工厂的版本与应用程序上下文的版本匹配。这可以避免由于版本不匹配而导致的反序列化失败。
此外,将序列化ID设置为应用程序上下文的ID还可以提高代码的可维护性。如果应用程序上下文的ID发生更改,只需要更新Bean工厂的序列化ID即可,而不需要在整个代码库中搜索和更新所有与序列化相关的代码。
-
prepareBeanFactory方法,填充beanFactory属性[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mrIKc7mb-1685347461595)(C:\Users\Ric\Desktop\每日总结\后端\spring\深入了解Spring\image-20210719155756828.png)]
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.setBeanClassLoader(this.getClassLoader()); if (!shouldIgnoreSpel) { beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); } beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment())); beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class); beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); if (!NativeDetector.inNativeImage() && beanFactory.containsBean("loadTimeWeaver")) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } if (!beanFactory.containsLocalBean("environment")) { beanFactory.registerSingleton("environment", this.getEnvironment()); } if (!beanFactory.containsLocalBean("systemProperties")) { beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean("systemEnvironment")) { beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment()); } if (!beanFactory.containsLocalBean("applicationStartup")) { beanFactory.registerSingleton("applicationStartup", this.getApplicationStartup()); } }
这段代码是Spring框架中的ApplicationContext的一个方法,用于准备BeanFactory,即对BeanFactory进行一些配置和初始化操作。具体来说,这个方法做了以下几件事情:
1. 设置BeanClassLoader:将当前ApplicationContext的ClassLoader设置为BeanFactory的ClassLoader,以便BeanFactory能够加载Bean的类。 2. 设置BeanExpressionResolver:如果shouldIgnoreSpel为false,则设置一个StandardBeanExpressionResolver作为BeanFactory的BeanExpressionResolver,用于解析Bean中的SpEL表达式。 3. 注册PropertyEditorRegistrar:注册一个ResourceEditorRegistrar,用于将字符串类型的属性值转换为Resource类型。 4. 添加BeanPostProcessor:添加一个ApplicationContextAwareProcessor,用于将ApplicationContext注入到实现了ApplicationContextAware接口的Bean中。 5. 忽略某些依赖接口:忽略一些依赖接口,如EnvironmentAware、EmbeddedValueResolverAware等,这些接口的实现类会在后续的Bean创建过程中被自动注入。 6. 注册可解析的依赖:注册一些可解析的依赖,如BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext等。 7. 添加BeanPostProcessor:添加一个ApplicationListenerDetector,用于检测实现了ApplicationListener接口的Bean,并将其注册到ApplicationEventMulticaster中。 8. 添加LoadTimeWeaverAwareProcessor:如果当前不是Native Image,并且BeanFactory中包含名为"loadTimeWeaver"的Bean,则添加一个LoadTimeWeaverAwareProcessor,用于将LoadTimeWeaver注入到实现了LoadTimeWeaverAware接口的Bean中。 9. 注册environment、systemProperties、systemEnvironment、applicationStartup:如果BeanFactory中没有名为"environment"、"systemProperties"、"systemEnvironment"、"applicationStartup"的Bean,则将当前ApplicationContext中的Environment、SystemProperties、SystemEnvironment、ApplicationStartup注册为单例Bean。
-
postProcessBeanFactory方法,对beanFactory进行操作,但是是空实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jivhl8i7-1685347461596)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719160034279.png)]
-
invokeBeanFactoryPostProcessors方法,调用各种beanFactory处理器(beanFactoryPostProcessor)
invokeBeanFactoryPostProcessors
是 Spring 框架中的一个方法,它的作用是在 BeanFactory 标准初始化之后,调用所有实现了
BeanFactoryPostProcessor
接口的类的
postProcessBeanFactory
方法,以便这些类可以对 BeanFactory 进行进一步的自定义修改。
BeanFactoryPostProcessor
接口是 Spring 框架中的一个扩展点,它允许开发者在 BeanFactory 标准初始化之后,对 BeanFactory 进行自定义修改。这些修改可以包括添加、删除、修改 BeanDefinition,修改属性值等等。通过实现
BeanFactoryPostProcessor
接口,开发者可以在 Spring 容器启动时,对容器中的 Bean 进行进一步的自定义处理,以满足特定的业务需求。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x4UjyHCC-1685347461596)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719170112805.png)]
-
registerBeanPostProcessors方法,准备beanPostProcessor[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZnvA9ZP-1685347461597)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719170549202.png)]
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList(); List<BeanPostProcessor> internalPostProcessors = new ArrayList(); List<String> orderedPostProcessorNames = new ArrayList(); List<String> nonOrderedPostProcessorNames = new ArrayList(); String[] var8 = postProcessorNames; int var9 = postProcessorNames.length; String ppName; BeanPostProcessor pp; for(int var10 = 0; var10 < var9; ++var10) { ppName = var8[var10]; if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, (List)priorityOrderedPostProcessors); List<BeanPostProcessor> orderedPostProcessors = new ArrayList(orderedPostProcessorNames.size()); Iterator var14 = orderedPostProcessorNames.iterator(); while(var14.hasNext()) { String ppName = (String)var14.next(); BeanPostProcessor pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, (List)orderedPostProcessors); List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList(nonOrderedPostProcessorNames.size()); Iterator var17 = nonOrderedPostProcessorNames.iterator(); while(var17.hasNext()) { ppName = (String)var17.next(); pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, (List)nonOrderedPostProcessors); sortPostProcessors(internalPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, (List)internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
这里将所有的实现了beanpostprocessor接口的processor都注册进beanFactory中
这段代码的作用是注册BeanPostProcessor,BeanPostProcessor是Spring框架中的一个扩展点,用于在Bean实例化、依赖注入、初始化等过程中对Bean进行增强处理。这个方法会根据BeanPostProcessor的实现类的不同,将其分为三类:实现了PriorityOrdered接口的、实现了Ordered接口的和其他的。然后对这三类BeanPostProcessor分别进行排序和注册。
具体来说,这个方法会先获取所有实现了BeanPostProcessor接口的Bean的名称,然后根据实现的接口类型将其分为三类。实现了PriorityOrdered接口的BeanPostProcessor会被放入priorityOrderedPostProcessors集合中,实现了Ordered接口的BeanPostProcessor会被放入orderedPostProcessorNames集合中,其他的BeanPostProcessor会被放入nonOrderedPostProcessorNames集合中。
接着,对priorityOrderedPostProcessors和orderedPostProcessorNames集合中的BeanPostProcessor进行排序,排序的规则是根据实现的接口类型和order属性值进行排序。排序后,将它们分别注册到beanFactory中。
最后,将nonOrderedPostProcessorNames集合中的BeanPostProcessor注册到beanFactory中,并将实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor放入internalPostProcessors集合中。对internalPostProcessors集合中的BeanPostProcessor进行排序后,也将其注册到beanFactory中。
最后,还会添加一个ApplicationListenerDetector的BeanPostProcessor到beanFactory中,用于检测Bean是否实现了ApplicationListener接口,如果实现了,则将其注册到事件监听器中。
-
initMessageSource方法,实现国际化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XYSnvQ0P-1685347461598)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719171038203.png)] 这段代码的作用是初始化MessageSource,MessageSource是Spring框架中的一个接口,用于国际化和本地化处理。在Spring应用程序中,可以使用MessageSource接口来获取国际化的消息,以便在不同的语言环境下显示不同的消息。这个方法首先获取当前应用程序上下文中的BeanFactory,然后检查是否已经存在名为”messageSource”的Bean。如果存在,则将其赋值给messageSource属性,并检查是否存在父上下文,如果存在,则将父上下文中的MessageSource设置为当前MessageSource的父MessageSource。如果不存在,则创建一个DelegatingMessageSource实例,并将其设置为messageSource属性的值。然后将这个DelegatingMessageSource实例注册到BeanFactory中,并命名为”messageSource”。最后,如果日志级别为TRACE,则输出日志信息。
-
initApplicationEventMulticaster方法,初始化事件监听器、多路广播器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nRmBUlNs-1685347461598)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719171243808.png)]
这段代码的作用是初始化ApplicationEventMulticaster,ApplicationEventMulticaster是Spring框架中的一个接口,用于管理和分发应用程序事件。在Spring应用程序中,可以使用ApplicationEventMulticaster接口来发布和监听应用程序事件。
这个方法首先获取当前应用程序上下文中的BeanFactory,然后检查是否已经存在名为”applicationEventMulticaster”的Bean。如果存在,则将其赋值给applicationEventMulticaster属性。如果不存在,则创建一个SimpleApplicationEventMulticaster实例,并将其设置为applicationEventMulticaster属性的值。然后将这个SimpleApplicationEventMulticaster实例注册到BeanFactory中,并命名为”applicationEventMulticaster”。最后,如果日志级别为TRACE,则输出日志信息。
发布和监听应用程序事件是Spring框架中的一个重要特性,它可以用于在应用程序中实现松耦合的组件之间的通信。下面是一些使用场景的例子:
1. 用户注册成功后,需要发送一封欢迎邮件。可以在用户注册成功后,发布一个UserRegisteredEvent事件,然后监听这个事件的邮件发送组件就可以收到这个事件,并发送欢迎邮件。 2. 在应用程序中,需要记录用户的操作日志。可以在用户执行操作时,发布一个UserOperationEvent事件,然后监听这个事件的日志记录组件就可以收到这个事件,并记录用户的操作日志。
以下为自定义事件,并且发布事件、监听事件的demo代码:
@Component public class AppEventListener implements ApplicationListener<CustomEvent> { @Override public void onApplicationEvent(CustomEvent event) { System.out.println("Received custom event - " + event.getMessage()); } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AppEventListener.class); CustomEvent event = new CustomEvent(new Object(), "Hello, world!"); context.refresh(); context.publishEvent(event); // 应用程序运行中... context.close(); } }
@Component public class CustomEvent extends ApplicationEvent { private String message; public CustomEvent(Object source, String message) { super(source); this.message = message; } public String getMessage() { return message; } }
-
registerListeners方法,将所有的Listener对象注册到广播器中。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NC1S2aP4-1685347461599)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719171504749.png)]
finishBeanFactoryInitialization方法核心
-
finishBeanFactoryInitialization方法,实例化所有剩余非懒加载的对象[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M2LbjgXF-1685347461599)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719172613735.png)]
- 如果bean工厂中包含名为“conversionService”的bean,并且它的类型是ConversionService,则将它设置为bean工厂的转换服务。
- 如果bean工厂中没有嵌入式值解析器,则添加一个嵌入式值解析器,用于解析占位符。
- 对于所有实现了LoadTimeWeaverAware接口的bean,调用getBean()方法以确保它们已经被实例化。
- 设置bean工厂的临时类加载器为null。
- 冻结bean工厂的配置,以防止进一步的修改。
- 预实例化所有单例bean。
重点为preInstantiateSingletons方法 他具体使用了反射实例化了bean对象。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x4HsVTXS-1685347461600)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719172941076.png)]
这段代码是 Spring Framework 中的一个方法,用于预先实例化所有的单例 bean。下面是对代码的详细解读和优化建议:
-
首先,该方法会记录日志,如果日志级别为 TRACE,则会输出 “Pre-instantiating singletons in ” + this。
-
接着,该方法会获取所有的 bean 名称,并遍历这些 bean 名称。
-
对于每个 bean 名称,该方法会获取对应的 bean 定义,并判断该 bean 是否为抽象类、是否为单例、是否为懒加载。
-
如果该 bean 是 FactoryBean,则会获取 FactoryBean 实例,并判断是否需要立即初始化。
-
最后,该方法会返回所有的单例 bean 实例。具体实现如下:
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = this.transformedBeanName(name); Object sharedInstance = this.getSingleton(beanName); Object beanInstance; if (sharedInstance != null && args == null) { if (this.logger.isTraceEnabled()) { if (this.isSingletonCurrentlyInCreation(beanName)) { this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); } else { if (this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = this.getParentBeanFactory(); if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) { String nameToLookup = this.originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); } if (args != null) { return parentBeanFactory.getBean(nameToLookup, args); } if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } return parentBeanFactory.getBean(nameToLookup); } if (!typeCheckOnly) { this.markBeanAsCreated(beanName); } StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name); try { if (requiredType != null) { beanCreation.tag("beanType", requiredType::toString); } RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); this.checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); String[] var12; if (dependsOn != null) { var12 = dependsOn; int var13 = dependsOn.length; for(int var14 = 0; var14 < var13; ++var14) { String dep = var12[var14]; if (this.isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } this.registerDependentBean(dep, beanName); try { this.getBean(dep); } catch (NoSuchBeanDefinitionException var31) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31); } } } if (mbd.isSingleton()) { sharedInstance = this.getSingleton(beanName, () -> { try { return this.createBean(beanName, mbd, args); } catch (BeansException var5) { this.destroySingleton(beanName); throw var5; } }); beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { var12 = null; Object prototypeInstance; try { this.beforePrototypeCreation(beanName); prototypeInstance = this.createBean(beanName, mbd, args); } finally { this.afterPrototypeCreation(beanName); } beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean ��" + beanName + "'"); } Scope 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, () -> { this.beforePrototypeCreation(beanName); Object var4; try { var4 = this.createBean(beanName, mbd, args); } finally { this.afterPrototypeCreation(beanName); } return var4; }); beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException var30) { throw new ScopeNotActiveException(beanName, scopeName, var30); } } } catch (BeansException var32) { beanCreation.tag("exception", var32.getClass().toString()); beanCreation.tag("message", String.valueOf(var32.getMessage())); this.cleanupAfterBeanCreationFailure(beanName); throw var32; } finally { beanCreation.end(); } } return this.adaptBeanInstance(name, beanInstance, requiredType); }
-
首先,该方法会将 bean 名称转换为规范化的 bean 名称,并尝试从单例缓存中获取 bean 实例。
-
如果单例缓存中存在 bean 实例,则直接返回该实例。
-
如果单例缓存中不存在 bean 实例,则判断该 bean 是否正在创建中,如果是,则抛出 BeanCurrentlyInCreationException 异常。
-
如果存在父级 BeanFactory,并且当前 BeanFactory 中不存在该 bean 的定义,则委托给父级 BeanFactory 进行处理。
-
如果需要创建新的 bean 实例,则先标记该 bean 已经被创建,然后开始创建 bean 实例。
-
创建 bean 实例时,会先检查该 bean 的依赖关系,如果存在循环依赖,则抛出 BeanCreationException 异常。
-
如果该 bean 是单例,则先尝试从单例缓存中获取 bean 实例,如果不存在,则创建新的 bean 实例,并将其放入单例缓存中。
-
如果该 bean 是原型,则直接创建新的 bean 实例。
-
如果该 bean 是其他作用域,则委托给对应的 Scope 进行处理。
-
最后,该方法会将 bean 实例适配为指定类型,并返回该实例。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isTraceEnabled()) {
this.logger.trace(“Creating instance of bean ‘” + beanName + “’”);
}RootBeanDefinition mbdToUse = mbd; Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException var9) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9); } Object beanInstance; try { beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse); if (beanInstance != null) { return beanInstance; } } catch (Throwable var10) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10); } try { beanInstance = this.doCreateBean(beanName, mbdToUse, args); if (this.logger.isTraceEnabled()) { this.logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) { throw var7; } catch (Throwable var8) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8); } }
- 方法签名
-
方法签名中的@Nullable注解表示参数args可以为null。
- 解析Bean的Class
首先通过resolveBeanClass方法解析Bean的Class,如果beanClass不为null且不是public的,且mbd中没有设置允许非public访问,则抛出BeanCreationException异常。这里建议在抛出异常时,将异常信息中的beanName和beanClass.getName()打印出来,方便排查问题。
优化建议:可以在BeanDefinition中增加一个属性,用于标识是否允许非public访问,这样就不需要每次都判断了。
- 实例化Bean
如果mbd中设置了instanceSupplier,则通过该Supplier获取Bean实例;如果mbd中设置了factoryMethodName,则通过该方法实例化Bean;否则,根据构造函数参数的解析情况,选择合适的构造函数实例化Bean。
优化建议:可以在BeanDefinition中增加一个属性,用于标识是否使用构造函数实例化Bean,这样就不需要每次都判断了。
- 解析构造函数
如果构造函数参数已经解析过,则直接根据是否需要自动装配来选择合适的构造函数实例化Bean;否则,通过BeanPostProcessor解析构造函数,如果没有找到合适的构造函数,则根据mbd中的信息选择合适的构造函数实例化Bean。
优化建议:可以在BeanDefinition中增加一个属性,用于缓存已经解析过的构造函数,这样就不需要每次都重新解析了。
- 返回BeanWrapper
最后返回一个BeanWrapper对象,该对象包装了实例化的Bean对象和Bean的元数据信息。
最终通过反射生成对应的bean对象。
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Object factoryBean, Method factoryMethod, Object... args) { try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(() -> { ReflectionUtils.makeAccessible(factoryMethod); return null; }); } else { ReflectionUtils.makeAccessible(factoryMethod); } Method priorInvokedFactoryMethod = (Method)currentlyInvokedFactoryMethod.get(); Object var9; try { currentlyInvokedFactoryMethod.set(factoryMethod); Object result = factoryMethod.invoke(factoryBean, args); if (result == null) { result = new NullBean(); } var9 = result; } finally { if (priorInvokedFactoryMethod != null) { currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod); } else { currentlyInvokedFactoryMethod.remove(); } } return var9; } catch (IllegalArgumentException var16) { throw new BeanInstantiationException(factoryMethod, "Illegal arguments to factory method '" + factoryMethod.getName() + "'; args: " + StringUtils.arrayToCommaDelimitedString(args), var16); } catch (IllegalAccessException var17) { throw new BeanInstantiationException(factoryMethod, "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", var17); } catch (InvocationTargetException var18) { String msg = "Factory method '" + factoryMethod.getName() + "' threw exception"; if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory && ((ConfigurableBeanFactory)owner).isCurrentlyInCreation(bd.getFactoryBeanName())) { msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider declaring the factory method as static for independence from its containing instance. " + msg; } throw new BeanInstantiationException(factoryMethod, msg, var18.getTargetException()); } } }
这段代码是 Spring Framework 中的一个方法,用于实例化一个 Bean。具体来说,它会调用一个工厂方法(factoryMethod)来创建一个对象,并返回该对象的实例。
下面是对代码的详细解读:
- 首先,该方法会尝试通过反射调用 factoryMethod 方法来创建一个对象。factoryMethod 方法通常是一个静态方法或者是一个实例方法,它会返回一个对象实例。
- 在调用 factoryMethod 方法之前,该方法会使用 ReflectionUtils.makeAccessible() 方法来确保 factoryMethod 方法是可访问的。这是因为 factoryMethod 方法可能是一个私有方法,需要使用 ReflectionUtils.makeAccessible() 方法来打开访问权限。
- 在调用 factoryMethod 方法之前,该方法会将当前正在调用的工厂方法设置为 factoryMethod。这是为了在发生异常时能够正确地恢复当前正在调用的工厂方法。
- 如果 factoryMethod 方法返回 null,则该方法会创建一个 NullBean 对象并返回。
- 在调用 factoryMethod 方法之后,该方法会将当前正在调用的工厂方法恢复为之前的值。
- 如果 factoryMethod 方法抛出异常,则该方法会根据异常类型抛出相应的异常。如果是 IllegalArgumentException,则会抛出 BeanInstantiationException 异常,并将异常信息设置为“Illegal arguments to factory method ‘factoryMethod.getName()’; args: args”。如果是 IllegalAccessException,则会抛出 BeanInstantiationException 异常,并将异常信息设置为“Cannot access factory method ‘factoryMethod.getName()’; is it public?”。如果是 InvocationTargetException,则会抛出 BeanInstantiationException 异常,并将异常信息设置为“Factory method ‘factoryMethod.getName()’ threw exception”。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = this.createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } synchronized(mbd.postProcessingLock) { if (!mbd.postProcessed) { try { this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable var17) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17); } mbd.postProcessed = true; } } boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName); if (earlySingletonExposure) { if (this.logger.isTraceEnabled()) { this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } this.addSingletonFactory(beanName, () -> { return this.getEarlyBeanReference(beanName, mbd, bean); }); } Object exposedObject = bean; try { this.populateBean(beanName, mbd, instanceWrapper); exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) { throw (BeanCreationException)var18; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18); } if (earlySingletonExposure) { Object earlySingletonReference = this.getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) { String[] dependentBeans = this.getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length); String[] var12 = dependentBeans; int var13 = dependentBeans.length; for(int var14 = 0; var14 < var13; ++var14) { String dependentBean = var12[var14]; if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."); } } } } try { this.registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject; } catch (BeanDefinitionValidationException var16) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16); } }
-
finishBeanFactoryInitialization
此方法是
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) { beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class)); } if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver((strVal) -> { return this.getEnvironment().resolvePlaceholders(strVal); }); } String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); String[] var3 = weaverAwareNames; int var4 = weaverAwareNames.length; for(int var5 = 0; var5 < var4; ++var5) { String weaverAwareName = var3[var5]; this.getBean(weaverAwareName); } beanFactory.setTempClassLoader((ClassLoader)null); beanFactory.freezeConfiguration(); beanFactory.preInstantiateSingletons(); }
- 完成实例化之后对属性赋初始值与调用Aware方法。
-
循环依赖
什么是循环依赖
-
循环依赖是指:循环依赖就是循环引用,就是两个或多个bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环。此处不是循环调用,循环调用是方法之间的环调用
-
如:Bean A的属性中含有Bean B,Bean B的属性中含有Bean A 。这样,在对象实例化之后填充属性时,会循环的注入彼此的对象。
怎么解决循环依赖
使用
三级缓存
,既三个map容器。 -
三级缓存的名称和分别储存的内容
- 一级缓存singletonObjects,存放成品对象,既完整以Bean对象(已实例化,已初识化)
- 二级缓存earlySingletonObjects,存放半成品对象(已实例化,未初始化)
- 三级缓存singletonFactories,存放lambda表达式,来完成代理对象的覆盖过程
-
三级缓存的查找顺序
一、二、三级依次查询[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-flNwYuiB-1685347461600)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210724162847387.png)]
以A注入B,B注入A为例:
A属性注入前就把lambda表达式放入了第三级缓存,所以B再注入A的时候会从第三级缓存中找到A的lambda表达式并执行,然后将半成品Bean放入第二级缓存,所以此时B注入的只是半成品的A对象,B创建完成后返回给A注入,A继续初始化,完成创建。
注意: B注入的半成品A对象只是一个引用,所以之后A初始化完成后,B这个注入的A就随之变成了完整的A
使用三级缓存解决循环依赖的过程
-
思想:创建对象时将实例化和初始化分开处理,提前暴露对象。
图解:以Bean A、Bean B相互将对方作为自己的属性为例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o1gIPkrh-1685347461600)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210724161652939.png)]
-
Spring扩展机制
-
利用BeanPostProcessor和BeanFactoryPostProcessor
-
一、利用后置处理器扩展Spring容器
Bean后置处理器(BeanPostProcessor 接口)
如果希望在Spring容器完成实例化、配置和初始化bean之后实现某些自定义逻辑, 则可以实现一个或多个 BeanPostProcessor 接口。BeanPostProcessor中有两个抽象方法:postProcessBeforeInitialization方法:在初始化方法(InitializingBean的afterPropertiesSet、init-method指定的方法等)之前调用
postProcessAfterInitialization方法:在初始化方法(InitializingBean的afterPropertiesSet、init-method指定的方法等)之后调用 -
二、ApplicationListener
监听容器发布的事件,实现一个监听器的步骤:1、编写一个监听器(实现ApplicationListener类)来监听某个事件(ApplicationEvent极其子类)
2、把监听器加入到容器中
3、只要容器中有相关事件发布,就能监听到这个事件
ContextRefreshedEvent : 容器刷新完成(所有bean都完成创建)会发布这个事件
ContextClosedEvent : 关闭容器会发布这个事件
4、手动发布一个事件:applicationContext.publishEvent()@Component
public class MyApplicationListener implements ApplicationListener{
//当容器中发布此事件,方法会得到触发 @Override public void onApplicationEvent(ApplicationEvent event) { System.out.println("收到事件:"+event); }
-
三、获取容器底层组件(各种Aware)
自定义组件想要使用Spring容器底层的一些组件(ApplicationContext, Environment,BeanFactory等),自定义组件需要实现XXXAware接口(继承Aware接口),在创建对象的时候,Spring会调用接口规定的方法注解相关组件,把Spring底层的一些组件注入到自定义的Bean中。
-