您现在的位置是:首页 > 文章详情

spring 扩展功能心得(一)

日期:2020-01-13点击:387

spring作为现在最火的开发框架,熟练的使用spring和扩展功能,能大大提高开发效率
首先从spring的启动来看,spring启动的核心方法是 refresh 方法,该方法定义在AbstractApplicationContext.class
下面上代码 基于spring4.3.18,基于ClassPathXmlApplicationContext

 public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { //前置刷新工作,可以进行一些环境变量的校验 this.prepareRefresh(); //生成beanFactory 在生成过程中加载bean定义文件(spring.xml和spring注解等) ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); //bean工厂准备工作 this.prepareBeanFactory(beanFactory); try { //加载postProcessBeanFactory this.postProcessBeanFactory(beanFactory); //调用postProcessBeanFactory,可以对bena工厂的属性以及对某些特定beanDefinition 修改属性 this.invokeBeanFactoryPostProcessors(beanFactory); //注册bean定义处理器,在bean进行初始化时,可以进行前置处理和后置处理 this.registerBeanPostProcessors(beanFactory); //初始化message信息 国际化使用 this.initMessageSource(); //初始化时间转发器 this.initApplicationEventMulticaster(); //模板方法,需要自己自定义 this.onRefresh(); //注册监听器 this.registerListeners(); //实例化bean this.finishBeanFactoryInitialization(beanFactory); //完成bean加载,发送refresh完成事件 this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }

1 prepareRefresh 刷新前准备事件

可以重写initPropertySources方法,进行环境变量参数以及其他参数校验
demo如下

public class MyContext extends ClassPathXmlApplicationContext { public MyContext(String...configLocations) { super(configLocations); } public MyContext(String[] configLocations,boolean refresh) { super(configLocations,refresh); } protected void initPropertySources(){ getEnvironment().setRequiredProperties("envir"); System.out.println( "envirment envir:"+getEnvironment().getSystemEnvironment().get("envir")); } public static void main(String[] args) { ApplicationContext context = new MyContext("spring.xml"); } }

在spring加载时,getEnvironment().setRequiredProperties() 方法,
在没有“envir” 环境变量时,抛出异常,在项目启动阶段将问题抛出,减少问题排查难度
2obtainFreshBeanFactory 生成beanFactory 加载bean定义文件

 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //核心操作,由AbstractRefreshableApplicationContext 进行实现 this.refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = this.getBeanFactory(); if (this.logger.isDebugEnabled()) { this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory); } return beanFactory; }

AbstractRefreshableApplicationContext.refreshBeanFactory()

 protected final void refreshBeanFactory() throws BeansException { //在获取到context后,可以进行手动refresh,在二次refresh时,需要销毁初始化创建的beanFactory if (this.hasBeanFactory()) { //判断是否已经存在了beanFactory this.destroyBeans(); //销毁所有bean对象,释放内存,主要是将存储bean和bean定义的map进行clear操作 this.closeBeanFactory();//关闭beanFactory,将序列化ID置为 null然后将beanFactory置为null } try { //创建beanFactory DefaultListableBeanFactory beanFactory = this.createBeanFactory(); //设置序列化ID 默认为:启动类名+@+启动类对象的hashCode.toHexString beanFactory.setSerializationId(this.getId()); //定义beanFactory 主要是设置是否允许Bean定义覆盖和循环引用(定义覆盖就是同一个名字有多个类,以后面的类为准) this.customizeBeanFactory(beanFactory); //加载bean定义文件,读取.xml文件 this.loadBeanDefinitions(beanFactory); Object var2 = this.beanFactoryMonitor; synchronized(this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException var5) { throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5); } }

关于上面说到的允许Bean定义覆盖 可以参考一下demo 实现一个bean多定义,以后加载的bean为准
image
image
image
image
到这一步 已经完成了bean信息定义的加载,具体的怎么读取配置文件在此不做解析

原文链接:https://yq.aliyun.com/articles/742619
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章