深入了解 Spring IOC DI 原理

什么是 IOC

IOC 被称为控制反转,通俗的说就是 我们需要使用一个对象而我们不在由自己去实现控制而交给Spring框架来控制对象的使用。

先上图:
未使用spring框架
在这里插入图片描述
使用spring框架
在这里插入图片描述
可以看到 Spring将我们的控制权由对象A转移到Spring进行。

  1. 那么什么是DI( 依赖注入 )?
    这个虽然和控制反转将的是一个概念,但是DI是从被调用者的角度来讲的。如上图,我们被依赖的对象B不需要由A来控制而是需要通过我们的Spring来将B对象注入到Spring中然后直接由A来使用,所以叫依赖注入。

  2. 为什么使用Spring IOC
    当我们一个庞大的项目需要用到很多的对象,如果每使用一个对象都要由程序员去new 的话会造成大量的工作量。而最重要的一点就是管理问题,就像一个公司 一样,如果所有的人员都可以互相调度使用那么必定会造成一个混乱不堪的现象。但Spring IOC 容器那么就会充当一个管理调度的工作,他可以给人员提供一个有序的管理。

  3. 深入 Spring IOC
    IOC 架构 有 ApplicationContext 和 BeanFactory 两种实现方法。
    根据我们的实例分析源码:

首先我们有一个目标类Library,如下

public class Library {
private String id;

private String address;


public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

@Override
public String toString() {
    return "com.wy.bean.Library{" +
            "id='" + id + '\'' +
            ", address='" + address + '\'' +
            '}';
}

}
这里我们通过ApplicationContext对配置信息进行装配并进行实例化(在FileSystemXmlApplicationContext 中实例化)

ApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/application.xml");
Library library =  (Library) context.getBean("library");

而BeanFactory是先进行xml装配而不进行实例化的,他会在getBean()时候进行实例化

Resource resource=new ClassPathResource("application.xml");
        BeanFactory factory=new DefaultListableBeanFactory();
        BeanDefinitionReader bdr=new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory);
        bdr.loadBeanDefinitions(resource);

        BeanFactory factory2 =  new XmlBeanFactory(resource);

        Library library2 =(Library) factory2.getBean("library");
  1. ApplicationContext 实现方式
    这里我们先介绍一下Spring ApplicationContext,这个模块是我们的启动配置模块,称为Spring的上下文。并且 ApplicationContext具有BeanFactory的所有功能。如下图:
    在这里插入图片描述
    因为ApplicationContext实现了BeanFatory的所有功能,并且还有许多其他功能,所以通常使用ApplicationContext加载文件并进行ioc的管理。这里先只对BeanFactory进行深入。

  2. BeanFactory
    BeanFactory基础架构:
    在这里插入图片描述

BeanFactory基础接口
BeanFactory是我们的顶级接口,其接口属性如下:
在这里插入图片描述

BeanFactory接口属性
getBean() 方法:该方法实现是在 AbstractBeanFactory 中实现

public Object getBean(String name, Object... args) throws BeansException {
    return this.doGetBean(name, (Class)null, args, false);
}

真的方法应该是doGetBean(),可大概了解一下

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        //转化Bean名字
        String beanName = this.transformedBeanName(name);
        //根据beanName获取单例模式的bean,如果没有则进行注册,有关单例模式可以查看我的另一篇单例的文章
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            if (this.logger.isTraceEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
           //从实例类中获取实例
            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            //校验原型是否在创建
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            //获取此实例父级容器
            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                //instanceof 判断parent..Factory是否是一个Abs..Factory的实例
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }
                 //从父级容器中中获取bean
                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }

                return parentBeanFactory.getBean(nameToLookup);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }

                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }

                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    var11 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.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 name '" + scopeName + "'");
                    }

                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            this.beforePrototypeCreation(beanName);

                            Object var4;
                            try {
                                var4 = this.createBean(beanName, mbd, args);
                            } finally {
                                this.afterPrototypeCreation(beanName);
                            }

                            return var4;
                        });
                        bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var23) {
                        throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
                    }
                }
            } catch (BeansException var26) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var26;
            }
        }

        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = this.getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                } else {
                    return convertedBean;
                }
            } catch (TypeMismatchException var25) {
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
                }

                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        } else {
            return bean;
        }
    }

我们仔细看其中的这样其中有下面一段代码,我们在创建Bean的时候根据我们的属性去设置,分别根据我们的配置(单例,原型)执行不同的实例化方式,最后都到createBean()中去进行实例化

  //单例模式
if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            //创建实例
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
//原型模式
                } else if (mbd.isPrototype()) {
                    var11 = null;
                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                       //创建实例
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
//scope 模型
                } else {
                    String scopeName = mbd.getScope();
                    Scope scope = (Scope)this.scopes.get(scopeName);
                    if (scope == null) {如下
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
createBean()方法如下 ,其真正实例化的方法是在doCreateBean()中

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)  
           throws BeanCreationException {  
       if (logger.isDebugEnabled()) {  
           logger.debug("Creating instance of bean '" + beanName + "'");  
       }  
       //判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载  
       resolveBeanClass(mbd, beanName);  
       //校验和准备Bean中的方法覆盖  
       try {  
           mbd.prepareMethodOverrides();  
       }  
       catch (BeanDefinitionValidationException ex) {  
           throw new BeanDefinitionStoreException(mbd.getResourceDescription(),  
                   beanName, "Validation of method overrides failed", ex);  
       }  
       try {  
           //如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建//Bean的代理对象  
           Object bean = resolveBeforeInstantiation(beanName, mbd);  
           if (bean != null) {  
               return bean;  
           }  
       }  
       catch (Throwable ex) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
                   "BeanPostProcessor before instantiation of bean failed", ex);  
       }  
       //真正的创建bean的方法
       Object beanInstance = doCreateBean(beanName, mbd, args);  
       if (logger.isDebugEnabled()) {  
           logger.debug("Finished creating instance of bean '" + beanName + "'");  
       }  
       return beanInstance;  
   }  

doCreateBean()方法的详细代码解释

 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
       //封装被创建的Bean对象  
       BeanWrapper instanceWrapper = null;  
       if (mbd.isSingleton()){
            //单态模式的Bean,先从容器中缓存中获取同名Bean  
           instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
       }  
       if (instanceWrapper == null) {  
           //创建实例对象  
           instanceWrapper = createBeanInstance(beanName, mbd, args);  
       }  
       final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  
       //获取实例化对象的类型  
       Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  
       //调用PostProcessor后置处理器  
       synchronized (mbd.postProcessingLock) {  
           if (!mbd.postProcessed) {  
               applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
               mbd.postProcessed = true;  
           }  
       }  
       // Eagerly cache singletons to be able to resolve circular references  
       //向容器中缓存单态模式的Bean对象,以防循环引用  
       boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&  
               isSingletonCurrentlyInCreation(beanName));  
       if (earlySingletonExposure) {  
           if (logger.isDebugEnabled()) {  
               logger.debug("Eagerly caching bean '" + beanName +  
                       "' to allow for resolving potential circular references");  
           }  
           //这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用  
           addSingletonFactory(beanName, new ObjectFactory() {  
               public Object getObject() throws BeansException {  
                   return getEarlyBeanReference(beanName, mbd, bean);  
               }  
           });  
       }  
       //Bean对象的初始化,依赖注入在此触发  
       //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean  
       Object exposedObject = bean;  
       try {  
           //将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象  
           populateBean(beanName, mbd, instanceWrapper);  
           if (exposedObject != null) {  
               //初始化Bean对象  
               exposedObject = initializeBean(beanName, exposedObject, mbd);  
           }  
       }  
       catch (Throwable ex) {  
           if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
               throw (BeanCreationException) ex;  
           }  
           else {  
               throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);  
           }  
       }  
       if (earlySingletonExposure) {  
           //获取指定名称的已注册的单态模式Bean对象  
           Object earlySingletonReference = getSingleton(beanName, false);  
           if (earlySingletonReference != null) {  
               //根据名称获取的以注册的Bean和正在实例化的Bean是同一个  
               if (exposedObject == bean) {  
                   //当前实例化的Bean初始化完成  
                   exposedObject = earlySingletonReference;  
               }  
               //当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象  
               else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
                   String[] dependentBeans = getDependentBeans(beanName);  
                   Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);  
                   //获取当前Bean所依赖的其他Bean  
                   for (String dependentBean : dependentBeans) {  
                       //对依赖Bean进行类型检查  
                       if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
                           actualDependentBeans.add(dependentBean);  
                       }  
                   }  
                   if (!actualDependentBeans.isEmpty()) {  
                       throw new BeanCurrentlyInCreationException(beanName,  
                               "Bean with name '" + beanName + "' has been injected into other beans [" +  
                               StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
                               "] in its raw version as part of a circular reference, but has eventually been " +  
                               "wrapped. This means that said other beans do not use the final version of the " +  
                               "bean. This is often the result of over-eager type matching - consider using " +  
                               "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  
                   }  
               }  
           }  
       }  
       //注册完成依赖注入的Bean  
       try {  
           registerDisposableBeanIfNecessary(beanName, bean, mbd);  
       }  
       catch (BeanDefinitionValidationException ex) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);  
       }  
       return exposedObject;  
    }
到这一步了还是没有找到我们要的具体实例化的代码,那么进入我们的createBeanInstance(),这里选择了几种实例化的方式:工厂,自动装配,Bean的构造方法,默认的无参构造方法。

//创建Bean的实例对象  
   protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {  
       //检查确认Bean是可实例化的  
       Class beanClass = resolveBeanClass(mbd, beanName);  
       //使用工厂方法对Bean进行实例化  
       if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
                   "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());  
       }  
       if (mbd.getFactoryMethodName() != null)  {  
           //调用工厂方法实例化  
           return instantiateUsingFactoryMethod(beanName, mbd, args);  
       }  
       //使用容器的自动装配方法进行实例化  
       boolean resolved = false;  
       boolean autowireNecessary = false;  
       if (args == null) {  
           synchronized (mbd.constructorArgumentLock) {  
               if (mbd.resolvedConstructorOrFactoryMethod != null) {  
                   resolved = true;  
                   autowireNecessary = mbd.constructorArgumentsResolved;  
               }  
           }  
       }  
       if (resolved) {  
           if (autowireNecessary) {  
               //配置了自动装配属性,使用容器的自动装配实例化  
               //容器的自动装配是根据参数类型匹配Bean的构造方法  
               return autowireConstructor(beanName, mbd, null, null);  
           }  
           else {  
               //使用默认的无参构造方法实例化  
               return instantiateBean(beanName, mbd);  
           }  
       }  
       //使用Bean的构造方法进行实例化  
       Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  
       if (ctors != null ||  
               mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||  
               mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {  
           //使用容器的自动装配特性,调用匹配的构造方法实例化  
           return autowireConstructor(beanName, mbd, ctors, args);  
       }  
       //使用默认的无参构造方法实例化  
       return instantiateBean(beanName, mbd);  
   }   
   //使用默认的无参构造方法实例化Bean对象  
   protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {  
       try {  
           Object beanInstance;  
           final BeanFactory parent = this;  
           //获取系统的安全管理接口,JDK标准的安全管理API  
           if (System.getSecurityManager() != null) {  
               //这里是一个匿名内置类,根据实例化策略创建实例对象  
               beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {  
                   public Object run() {  
                       return getInstantiationStrategy().instantiate(mbd, beanName, parent);  
                   }  
               }, getAccessControlContext());  
           }  
           else {  
               //将实例化的对象封装起来  
               beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);  
           }  
           BeanWrapper bw = new BeanWrapperImpl(beanInstance);  
           initBeanWrapper(bw);  
           return bw;  
       }  
       catch (Throwable ex) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
       }  
   }

进入到 无参构造方法中 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 这段代码就发现,春天来了!实例化,wc!

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
                       //使用BeanUtil进行实例化
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// 使用CGLIB动态代理方法进行实例化
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

使用Beanutil 的实例化代码!使用的是反射的newInstance()方法!

return ctor.newInstance(argsWithDefaultValues);
通过以上代码算是了解到底层进行实例化的代理设计模式,CGLIB动态代理,进入动态代理我们发现下面这段代码,使用的是反射的newInstance()进行了最终的实例化!

				Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
				instance = enhancedSubclassConstructor.newInstance(args);

看完实例化的源码后我们总结一下BeanFactory实例化的简单流程:

  1. 通过使用BeanFacrory 的 getBean()接口 来告诉IOC容器需要根据beanName获取实例
  2. getBean() 由 AbstractBeanFactory 的 dogetBean()具实现
  3. doGetBean()中我们需要首先去获取是否存在,然后对配置信息进行一个判断。然后去进入到实例化的方法
  4. 进入 createBean() 选择在实例化前进行校验
  5. doCreateBean() 来对我们配置的模型进行实例化的具体实现并且在实例化后完成依赖注入。
  6. doCreateBean() 实例化的具体实现是在createBeanInstance()中进行的,他会根据我们的要求去进行相应的模式设计!
发布了18 篇原创文章 · 获赞 4 · 访问量 350

猜你喜欢

转载自blog.csdn.net/qq_38929920/article/details/105163309