IOC原理

http://www.cnblogs.com/ITtangtang/p/3978349.html

Spring的bean的创建是典型的工厂模式,BeanFactory定义了IOC容器的基本功能规范。而bean对象是具体如何产生的要看具体的IOC容器实现。

常用的IOC容器实现方式有四种,XmlBeanFactory就是针对最基本的IOC容器的实现(无法使用注解进行注入)。可以读取XML文件中的BeanDefination(xml中对bean的描述。)

IOC容器的初始化包括Bean资源文件定位,载入bean资源文件并注册beanDefination这两个基本的过程。 

ApplicationContext ctx = new ClassPathXmlApplicationContext("config/spring/beans.xml");做了些什么?

1.层层调用父类构造函数设置bean资源加载器

2.设置bean定义资源文件(配置文件)的路径

3.执行refresh()函数对bean定义资源文件进行载入:IOC容器里面维护了一个单例的BeanFactory,如果bean的配置有修改,也可以直接调用refresh方法,它将销毁之前的BeanFactory,重新创建一个BeanFactory。所以叫refresh也是能理解的。    

refresh()函数核心步骤:1.将xml配置文件转换成resource对象

                                       2、将Resource里定义的bean转换成同意的BeanDefination

                                       3.将BeanDefination注册到BeanFactory,完成BeanFactory的初始化。(BeanFactory中会维护一个BeanDefination的MAP)

 之后getBean的时候就会从BeanFactory中根据bean的beanDefination去实例化一个bean。

 

 

                                                                   

从getBean开始

 http://blog.csdn.net/lisongjia123/article/details/52134396

http://blog.csdn.net/zghwaicsdn/article/details/50910384

 

一:doGetBean方法;

1.判断beanName是否为空,为空抛出异常提示name不能为空,否则判断beanName是否以&开头,是的话去掉&。

2.执行getSingleton(beanName);获取bean的登记式单例模式的单例,如果需要的单例不为空的话返回已存在的单例,返回语句在方法结尾处。

if ((sharedInstance != null) && (args == null)) {
if (this.logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
}
else{
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

3.如果beanDefination中不存在指定bean的beanDefination并且父级容器不为空则去父级容器中请求bean

if ((parentBeanFactory != null) && (!containsBeanDefinition(beanName)))
{
String nameToLookup = originalBeanName(name);
if (args != null)
{
return parentBeanFactory.getBean(nameToLookup, args);
}

return parentBeanFactory.getBean(nameToLookup, requiredType);
}

4.获取beanDefination中当前请求bean所依赖的所有bean名称,不为空的话去递归调用getBean方法

String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (int i = 0; i < dependsOn.length; i++) {
String dependsOnBean = dependsOn[i];
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}

}

5.如果是单例模式创建单例模式的bean,如果是原型模式创建原型模式的bean(用户每次请求bean会创建一个新的实例),否则根据bean定义资源中配置的生命周期范围实例化bean。

 web应用程序中比较常用,比如request,session,application等生命周期。

if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
}
catch (BeansException ex)
{
AbstractBeanFactory.this.destroySingleton(beanName);
throw ex;}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}


else if (mbd.isPrototype())
{
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

 

else
{
String scopeName = mbd.getScope();
Scope scope = (Scope)this.scopes.get(scopeName);
if (scope == null)
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
try
{
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
AbstractBeanFactory.this.beforePrototypeCreation(beanName);
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
}
finally {
AbstractBeanFactory.this.afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

 

二:doCreateBean方法(AbstractAutowireCapableBeanFactory)

二.1用beanName和beanDefination为参数创建实例对象

instanceWrapper = createBeanInstance(beanName, mbd, args);

      三种方式实例化:

1.如果rootBeanDefination的工厂方法名不为空,用工厂方法模式创建实例。

if (mbd.getFactoryMethodName() != null)  {

2.如果方法传进来的参数args不为空使用自动装配方式实例化,容器的自动装配是根据参数类型匹配bean的构造方法。

 要想不为空,从getBean开始就得传

3.使用默认的无参构造方法实例化bean

此方式最常用:beandefination判断MethodOverrides()类中hashset集合性质的一个属性中维护的MethodOverride类是否为空,为空的话用反射机制来实例化,否则用CGLIB动态代理技术来进行实例化。

 

二.2.bean对象的初始化,依赖注入在此触发。 exposedObject 在初始化完成后返回作为依赖注入完成后的bean

Object exposedObject = bean;
try {

将bean实例对象封装,并且将bean定义中配置的属性值赋值实例对象
populateBean(beanName, mbd, instanceWrapper);

初始化bean对象
exposedObject = initializeBean(beanName, exposedObject, mbd);
}

http://www.cnblogs.com/davidwang456/p/4192318.html (BeanDefination是接口)

populateBean()方法:填充bean

1.获取容器解析bean定义资源时给beanDefination设置的属性值

PropertyValues pvs = mbd.getPropertyValues();

2.设置属性前先调用后置处理器

http://www.cnblogs.com/sishang/p/6576665.html(后置处理器:如果要在bean实例化、初始化前后加一些自己的逻辑处理,需要定义一个或多个BeanPostProcessor的实现类来,然后注册到IOC容器中。)

3.首先处理autoaire自动装配的注入

使用取得的当前Bean的属性名作为Bean的名字,向IoC容器getBean ,然后把从容器得到的Bean设置(setPropertyValues)到当前Bean的属性中去

4.解析

判断属性值是否需要解析,比如属性值为另一个bean的引用,需要先解析再注入

 

5.注入:依赖注入的过程就是将bean对象实例设置到它依赖的bean对象属性上去。

 

 



 
posted @ 2017-09-22 09:44  新生的小心情  阅读(197)  评论(0编辑  收藏  举报