Spring 之IOC容器(初级)
一、概念
1.容器:通俗的讲就是用来装东西的盒子,如果将东西装进容器里将使得我们对容器总的个体具备一定程度的可操作性,举个例子将1000个玻璃球放在一个瓶子里,执行如下的一些操作:
a) 瓶子中只允许存在一个蓝颜色的玻璃球(单例)
b) 为瓶子中黄颜色的玻璃球贴一个标签(切面)
c) 如果存在红颜色的玻璃球则必须存在唯一的一个黑颜色的玻璃球(依赖)
d) 欢迎补充
2.控制反转(Inversion of Control==IOC)&&依赖注入dependency injection (DI):通俗的理解我们要买一个杯子,一般的我们会主动的去超市买一个拿回来用,IOC的思想可以这么理解,我需要一个杯子我只需要告诉超市给我一个杯子,超市或者其它一个组织(超市或者组织扮演了容器的角色,自然“我”也应该处于容器的环境中)负责将杯子给我使用。总结如下:
a) 两个术语描述了同一个意思
b) IOC,主动变被动,需要什么只需要告诉某个组织(容器)即可
c) DI,需要什么就给你什么,社会主义的终极目标
3.Spring IOC:你能否想象得到如果将一个项目中的所有的Java对象都装在一个容器中,而各种类型的Java对象之间维持了一定的引用关系是多么有意义的一件事情吗?这将意味着我在使用一个Java对象的时候再也不需要显示的去New它了,只需要从IOC容器中获取一个即可。总结如下:
a) 用来装载、管理Java对象实例的“虚拟”容器
b) 本身也是一个Java类(面向对象语言的特性)
4.Spring Beans:通俗点,Bean指受IOC容器管理的Java对象
a) 有属性、构造器等一系列的属性
二、实现
1.IOC原型:由于面向对象语言特性Java中的容器依然是一个Java对象,这个Java对象使用某种数据结构(Map<String, Object>等)管理了若干Spring Bean对象,Spring IOC容器的顶级接口为BeanFactory,ApplicationContext接口拓展了BeanFactory接口提供了AOP的支持,通常情况下使用的都是ApplicationContext间接子类如WebApplicationContext、ClassPathXmlApplicationContext等。
2.实现,以ClassPathXmlApplicationContext的实例化为例
a) 在xml中定义Spring Beans
<bean id="hello" class="cn.com.zjf.model.Hello">
<!-- 配置Bean对象的属性 -->
<property name="message" value="Hello World!!"></property>
</bean>
b) 显示实例化IOC容器
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("ApplicationContext.xml");
c) 设置XML资源位置&&刷新IOC容器
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
d) 初始化IOC容器
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();
// 实例化剩余的非懒加载的单例Bean finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
e) finishBeanFactoryInitialization(beanFactory);做了什么
i. 获取所有Bean名称
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
ii. 遍历获取实例化Bean对象
for (String beanName : beanNames) {
getBean(beanName);
iii. 实例化Bean对象
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
iv. 将Bean对象存储至数据结构
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
3.从IOC容器中获取Bean对象,以获取id为hello的对象为例
a) 获取Bean对象
Hello hello=context.getBean("hello", Hello.class);
b) AbstractApplicationContext的getBean方法
public <T> T getBean(String name, Class<T> requiredType) throws BeansException
c) AbstractApplicationContext的doGetBean方法
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
d) 得到Bean对象(代码摘选)
Object singletonObject = this.singletonObjects.get(beanName);
Object sharedInstance = getSingleton(beanName);