深入探索IOC容器的实质

来源:互联网 发布:python 折线图 编辑:程序博客网 时间:2024/05/15 12:17
IOC容器初始化时,创建所有单例的bean,今天深入探索IOC容器的实质:

IOC容器初始化即创建ClassPathXmlApplicationContext对象,如下:

ApplicationContext ioc = new ClassPathXmlApplicationContex("applicationContext.xml");

其内部的创建代码如下:

ClassPathXmlApplicationContext类中的构造方法

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {this(new String[] {configLocation}, true, null);}

调用了本类的另一个构造器方法

ClassPathXmlApplicationContext

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {super(parent);//设置本地参数setConfigLocations(configLocations);if (refresh) {//创建IOC容器refresh();}}

创建IOC容器的方法在org.springframework.context.support.AbstractApplicationContext

@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//准备beanFactory// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();//初始化beanFactory// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}}}

初始化beanFactory即调用本类的方法,如下:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();//初始化所有的单实例bean// Instantiate all remaining (non-lazy-init) singletons.beanFactory.preInstantiateSingletons();}


至此初始化所有的单实例bean,调用org.springframework.beans.factory.support.DefaultListableBeanFactory的preInstantiateSingletons()方法

//创建所有的单实例bean@Overridepublic void preInstantiateSingletons() throws BeansException {if (this.logger.isDebugEnabled()) {this.logger.debug("Pre-instantiating singletons in " + this);}List<String> beanNames;//获得所有beanNamesynchronized (this.beanDefinitionMap) {// 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.beanNames = new ArrayList<String>(this.beanDefinitionNames);}//遍历所有beanName的集合for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {@Overridepublic Boolean run() {return ((SmartFactoryBean<?>) factory).isEagerInit();}}, getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}else {//从IOC容器中获取bean,如果没有这个bean,//就去创建一个bean,并返回,如果有就从容器中拿 getBean(beanName);}}}}


从IOC容器中获取bean,即执行org.springframework.beans.factory.support.AbstractBeanFactory类中的getBean方法

@Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}@Overridepublic <T> T getBean(String name, Class<T> requiredType) throws BeansException {return doGetBean(name, requiredType, null, false);}@Overridepublic Object getBean(String name, Object... args) throws BeansException {return doGetBean(name, null, args, false);}

所有的getbean方法皆调用了本类的doGetBean方法

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {...//根据beanName获得所有单例模式的beanObject sharedInstance = getSingleton(beanName);...

根据beanName获取所有单例模式的bean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

如下即是具体的方法代码

@Overridepublic Object getSingleton(String beanName) {return getSingleton(beanName, true);}protected Object getSingleton(String beanName, boolean allowEarlyReference) {//从这个类的singletonObjects属性中获取Object singletonObject = this.singletonObjects.get(beanName);...

而singtonObjects,此属性的定义如下:
/** Cache of singleton objects: bean name --> bean instance */private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

我们发现这些单例的对象其实是保存在一个map中
这个所谓的IOC容器就是一个map,所有的单例都保存在这个map中


具体流程:
ioc容器一启动就调用初始化---->AbstractApplicationContext.refresh()---->初始化所有的单实例对象
---->AbstractApplicationContext.finishBeanFactoryInitialization()----->调用getBean初始化bean
---->所有的getbean又调用AbstractBeanFactory.doGetbean();---->调用doGetBean的getSingleton(beanName);
---->第一次ioc初始化烦hi的是null,第二去调用getBean通过这个方法就已经返回了
bean实例,调用的是DefaultSingletonBeanRegistry.getSingleton();
就是从singletonObjects里面拿出对应的bean。
singletonObjects是一个map,声明如下,
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
这就是我们保存所有单实例对象的地方,ioc容器。
2 0
原创粉丝点击