1、IoC思想 .
如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)
2、Spring初始化IoC容器的过程。
Spring 先加载beanDefinition到beanFactory中(用map存储,key是beanName),beanDefinition是bean数据结构的一种映射。然后处理beanDefiniton(怎么处理?)。完成bean注册beanFactory中。在完成之前,先预实例化那些单例bean(lazy-init为false的)。
3、IoC容器的初始化包括BeanDefinition的Resource定位,载入和注册。
(1)、定位:使用BeanDefinitionReader读取资源applicationContext.xml文件。
(2)、载入:读取xml文件中定义的Bean,然后表示成IoC容器内部的数据结构beanDefinition,包括xml中定义的和component_scan自动扫描到的带有@service,@controller,@dao注解的bean。
疑问?spring是用哪个类解析xml中定义的component_scan路径并scan所有bean的?
(3)、注册:向IoC容器注册这些BeanDefinition的过程。通过调用BeanDefinitionRegistry接口的实现来完成的,这个注册是把载入过程解析到的BeanDefinition向IoC容器进行注册。在IoC内部是通过一个HashMap来保存这些BeanDefinition数据的
4、IoC容器的初始化不包含Bean依赖注入的实现,一般依赖注入发生在应用第一次向容器通过getBean索取Bean时。但可以根据BeanDefinition信息中的Lazyinit属性来设定。即为false时,在容器初始化完成后,就预实例化。
预实例化时,先从父类容器中判断是否有缓存,父类没有从子类容器判断是否有缓存。
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
synchronized (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.
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
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>() {
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
}
}
5、Spring IoC对于不同scope的对象是怎么管理的?
如果是single模式,那么直接取容器中的实例,那如果是原型模式,是每次getBean的时候,创建新实例吗?//TODO
6、为什么用Spring IoC而不是用工厂模式?
使用工厂模式时,调用者仍然需要定位到工厂,使调用者和工厂耦合到一起。需要调用被调用者时直接IoC依赖注入。
7、几种注入的不同@Resource,@Autowired,@Qualier?
TODO
8、IOC的注入方式?
参见这里》Spring常用的三种注入方式 构造函数注入,Setter注入,基于注解的注入
参考: