首页 > 编程知识 正文

java加载类的步骤,applicationlistener 用法

时间:2023-05-05 13:41:56 阅读:155583 作者:112

了解Spring ApplicationContext加载流程(1)上网查看文章,Spring Bean加载流程,https://www.cn blogs.com/zrtqsk/p/3735273 从以前的博客中,有了理解Spring IoC构成的脑图。 可以看到,通过BeanPostProcessor、BeanFactoryPostProcessor和BeanAware接口实现了Spring IoC的灵活扩展。 本文结合源代码,总结了Spring Bean的加载过程。

单从Spring ApplicationContext的脑图来理解Spring IoC的配置文章中,Spring IoC上下文的Bean定义方式有三种。 1、xml文件对齐; 2、注释配置3、用Java代码配置。 其实,这三种放置方式的区别在于元数据的数据源格式不同,最终加载元数据后与Spring对应的其实是BeanFactory,开发者通过该BeanFactory获取bean,达到控制逆转的功能

UML类图本文主要论述了annotationconfigapplicationcontext.class和abstractxmlapplicationcontext.class两个类,分别是如何用注释描述元数据的相关的接口继承关系如下。

在xml描述元数据中,接下来详细查看classpathxmlapplicationcontext.class的源代码。

构造函数publicclasspathxmlapplicationcontext (string [ ] config locations,boolean refresh,@ nullableapplicationcontextparent if(refresh ) ) { this.refresh; }调用了abstractapplicationcontext.refresh ()方法。 这个方法也是context加载的入口。

abstractapplicationcontext.refresh (public void refresh ) throws BeansException、 illegalstateexception { synchronized (this.startupshutdownmonitor ) startupstepcontextrefresh=this.application stup//* 1,初始化Context的BeanFactory,最终调用抽象方法: this.loadbeandefinitions (beanfactory )加载bean元数据。 2、数据源调用相应的方法,在XmlBeanDefinitionReader、AnnotatedBeanDefinitionReader中调用解析元数据*/configurablelistablebeanfactorybeanfactory=tonfigurablelistablebeanfactory/* 1、applicationcontextawareprocessor、aplice 设定要忽略的依存加载类3、设定已知的依存关系4、根据bean定义注册特殊的单一例子。 例如,systemProperties、 try { /*调用方法postProcessBeanFactory,不同的context实现类重载此方法以定制beanFactory加载完成后的操作的目的*/this.post startupstepbeanpostprocess=this.application startup.start (' spring.context.beans.post-process ' ); /*

调用所用定义的BeanFactoryPostProcessor,主要分两类:1、先调用BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry方法;2、再调用BeanFactoryPostProcessor.postProcessBeanFactory方法 */ this.invokeBeanFactoryPostProcessors(beanFactory); /* 扫描Context中所有beanPostProcessor,并注册到BeanFactory中 */ this.registerBeanPostProcessors(beanFactory); beanPostProcess.end(); //加载Message资源 this.initMessageSource(); //初始化事件广播属性,若context中有定义applicationEventMulticaster的bean,则getBean作为applicationEventMulticaster,否则使用SimpleApplicationEventMulticaster.class this.initApplicationEventMulticaster(); //定制动作定制接口,不同的context可以通过重载实现refresh特殊操作 this.onRefresh(); //把context中所有类型为ApplicationListener.class的bean注册到listener中 this.registerListeners(); /* beanFactory加载完毕后置动作,调用beanFactory.preInstantiateSingletons();预加载配置为单例类型的bean(单例实例初始化加载入口) */ this.finishBeanFactoryInitialization(beanFactory); /* 1、调用initLifecycleProcessor方法注册LifecycleProcessor,可定制LifecycleProcessor.class类型bean定制,否则返回DefaultLifecycleProcessor.class 2、调用lifecycleProcessor.onRefresh()方法 3、广播事件:ContextRefreshedEvent(this) */ 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(); } } }

整个Context加载的主要流程都在这个refresh方法中,而Bean的加载在Context加载流程中主要体现在ConfigurableListableBeanFactory.preInstantiateSingletons()方法中,接下来详细讲一下这个方法。

ConfigurableListableBeanFactory.preInstantiateSingletons()

源码:

@Overridepublic void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//判断只有bean为非抽象bean、且作用域为singleton且没有配置懒加载的时候才会预加载beanif (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);//若为工厂类,则特殊处理一下,SmartFactoryBean?否则直接调用getBean()if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans.../*找到所有SmartInitializingSingleton类型的bean,触发调用其afterSingletonsInstantiated()接口*/for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}

这里主要是调用了AbstractBeanFactory.getBean(String name)方法,将在搞懂Spring Context加载过程(二)文章中详细讲一下这个方法。

总结

文章中提到的类大概分为以下几个角色:
1、Context: 上下文类,主要是加载元数据,通过Reader类读取并解析元数据,转化为BeanDefination,初始化BeanFactory,并最终委托BeanFactory进行Bean的获取。
2、BeanFactory:Bean生命周期管理的核心,负责根据输入的条件返回对应的Bean实例
3、Reader:不同数据源的读取适配器,通过Reader解耦元数据读取与Context初始化逻辑,不同的Reader对应不同的配置方式。
4、不同的Context类型,比如GenericWebApplicationContext,可以通过重写AbstractApplicationContext.postProcessBeanFactory()方法、AbstractApplicationContext.onRefresh()方法在refresh过程中做一些定制化的操作
5、BeanFactory加载完后会调用调用注册的BeanFactoryPostProcessor、lifecycleProcessor.onRefresh()方法、广播事件:ContextRefreshedEvent(this),可以通过这几种途径定制后置事件
6、Registry,负责特定类型的Bean注册、获取,比如DefaultSingletonBeanRegistry
具体的单例Bean预加载逻辑可以看下一篇博客:一篇文章搞懂Spring单例循环依赖加载

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。