需求前提:在容器加载的过程中,需要要同时加载某些特殊的会阻塞线程的对象,例如(自动启动msn并自动登陆)。
问题描述:由于spring的初始化过程是单线程进行的,这种特殊的对象会导致线程阻塞,spring无法进行正常初始化。
解决方案:
1.使用监听器。
2.延时加载。
3.二次加载。
方案分析:
第一种方案:此方法使用单独的线程来启动这类资源,因此不会影响到spring自身的初始化。问题在于,一般在业务需求中,我会都会需要通过
spring从DB中获取数据后再启动这类对象,例如(msn的email和密码都存于DB中)。而这里的listener线程和spring的初始化线程是同时进行的,因此,spring
未初始化之前是无法获取DB中资源的。并用此类listener貌似无法被spring托管
第二种方案:此方法的思路是在spring初始化的过程中,不进行特殊对象的初始化。等spring初始化完毕,各种资源都就绪后,再进行特殊对象的初
始化。问题:1.无法自动加载。2.手动初始化用户进程也会被阻塞
第三种方案:三spring加载完毕后,进行再次初始化,这个可以在springloadlistendr里去做二次初始化(注:用多线程去做,此时spring已经初始
化完毕,所有资源都可以正常获取),这样即可保证spring正常初始化,也可以保证所有特殊对象正常初始化。
需求问题分析:
以前一直以为,这种特殊的对象spring会启动新线程来处理,后来深入了解spring后发现,其实spring并没有对这种对象特殊对待。因为为了保证初
始化的完整性,这种对象是必需要启动新线程来初始化的。而spring则是单线程解决一些依赖关系后按顺序初始化的。之所以对spring产生错误的理解,认为
它会处理这种对象,是因为在平时使用过程中,遇到过一些会阻塞线程的对象,但spring并没有被阻塞。例如说TimerFactoryBean定时器,在spring里配置后
并没有阻塞。今天仔细看了一下这个类调用的过程,结果发现原来这个类在调用过程中自己进行了线程处理,因此不会阻塞spring的初始化线程了。
总结:
对于一些不理解的东西,最好先去猜测它实现,然后看看源代码来验证猜测的正确性。对于spring源代码的分析,不难发现,所有会阻塞线程的对象
,都需要用户自己去处理使得它不会阻塞,spring是不负责进行这些检测的。因为对spring而言,它也不知道哪些对象需要特殊处理。即使知道,它启动新线
程来处理这些对象的时候,也无法保证所有的依赖对象都正确初始化。注:上面所说的特殊对象的初始化,并不是指实例的生成,而是指实例生成后对会阻塞
线程的方法的调用。