Spring深入理解之IOC创建并获取Bean

前言

上篇博客 主要说到了Spring IOC对bean类xml配置文件、使用反射等将其加载、解析并注册至Spring 容器中,以达到后期的使用操作。

但是,这个对象需要使用,依旧需要实例化操作,针对实例化,Spring就给整个项目进行了实现,但他是如何实现的?下面对此问题做具体分析。

断点测试

依旧使用之前的测试代码。

	@Test
	public void spring() {
		//1、获取beanfactory对象
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		//2、获取xml文件解析器
		XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		//3、加载指定xml文件,并自动解析、注册配置文件中的bean至beanFactory中
		xmlBeanDefinitionReader.loadBeanDefinitions("bean1.xml");
		UserDao ud = beanFactory.getBean(UserDao.class);
		Assert.notNull(ud,"UserDao 不能为空");
		ud.test();
	}

以及调用的类

public class UserDao {
	public void test() {
		System.out.println("UserDao test .....");
	}

	public UserDao() {
		System.out.println("UserDao().......");
	}

}

由于Spring创建一个bean(对类的实例化操作),必将会调用这个类的构造方法。由此本次测试断点可以打在如下所示位置:
Spring深入理解之IOC创建并获取Bean_第1张图片
spring()使用debug调试。

断点后的运行方法栈结构

Spring深入理解之IOC创建并获取Bean_第2张图片
由debug运行代码方法栈,可以看出,通过Spring创建并获取到实例化对象时,会有三类流程:通过beanFactory获取到bean的相关信息(class)创建bean实例化bean

接下来对该三类流程做具体分析。

获取bean

在这里插入图片描述
此时getBean(Class requiredType)中的requiredType值为:
Spring深入理解之IOC创建并获取Bean_第3张图片
是一个类信息,标识了全路径名称等。

其中,经过了resolveNamedBean(requiredType, args)操作,这个操作做了什么?

Spring深入理解之IOC创建并获取Bean_第4张图片
在这里插入图片描述
Spring深入理解之IOC创建并获取Bean_第5张图片
其中,getBeanNamesForType的完整源码为

	@Override
	public String[] getBeanNamesForType(Class<?> type) {
		return getBeanNamesForType(type, true, true);
	}
	@Override
	public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
		if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
			return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
		}
		//根据includeNonSingletons参数判断是否需要从缓存中获取
		Map<Class<?>, String[]> cache =
				(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
		//在缓存集合中,依据  class cn.linkpower.di.UserDao  获取对应的bean的别名信息
		String[] resolvedBeanNames = cache.get(type);
		
		if (resolvedBeanNames != null) {
			return resolvedBeanNames;
		}
		resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
		if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
			cache.put(type, resolvedBeanNames);
		}
		return resolvedBeanNames;
	}

在这里插入图片描述
经过处理后,此时的resolveNamedBean操作中,根据getBeanNamesForType(requiredType)获取到的数据信息为:[userDao]

Spring深入理解之IOC创建并获取Bean_第6张图片
之后会走下列流程。
Spring深入理解之IOC创建并获取Bean_第7张图片
Spring深入理解之IOC创建并获取Bean_第8张图片
即进入创建Bean环节。
其次,在doGetBean操作中,会判断需要创建Bean的单例、多例类型性质
Spring深入理解之IOC创建并获取Bean_第9张图片

创建bean

Spring深入理解之IOC创建并获取Bean_第10张图片

对象创建完成后,会校验对象是单例还是多例,如果是单例则找缓存,多例直接创建。

Spring深入理解之IOC创建并获取Bean_第11张图片
对象创建完成后,会继续判断对象中的依赖关系,进而对依赖的类实现创建操作。
Spring深入理解之IOC创建并获取Bean_第12张图片

实例化bean

创建Bean后,此时的bean

Spring深入理解之IOC创建并获取Bean_第13张图片
其中此时的instantiate各项参数数据信息为:
RootBeanDefinition bd:
Spring深入理解之IOC创建并获取Bean_第14张图片

Root bean: class [cn.linkpower.di.UserDao]; scope=singleton; abstract=false; 
lazyInit=false;autowireMode=0; dependencyCheck=0; autowireCandidate=true; 
primary=false; factoryBeanName=null; factoryMethodName=null;
initMethodName=null; destroyMethodName=null; 
defined in class path resource [bean1.xml]

String beanName :
Spring深入理解之IOC创建并获取Bean_第15张图片
BeanFactory owner :
Spring深入理解之IOC创建并获取Bean_第16张图片

org.springframework.beans.factory.support.DefaultListableBeanFactory@568ff82: 
defining beans [testDemo1,userDao,userDaos]; root of factory hierarchy

org.springframework.beans.factory.support.instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner)源码为:

@Override
	public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		// 判断 org.springframework.beans.factory.support.MethodOverrides中的Set 是否为空
		if (bd.getMethodOverrides().isEmpty()) {
			Constructor<?> constructorToUse;
			//加锁
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					// 返回 包装好的Bean的类(假设已经解决了)。
					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(new PrivilegedExceptionAction<Constructor<?>>() {
								@Override
								public Constructor<?> run() throws Exception {
									//返回包装好的类的构造方法
									return clazz.getDeclaredConstructor((Class[]) null);
								}
							});
						}
						else {
							constructorToUse =	clazz.getDeclaredConstructor((Class[]) null);
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			// 调用该方法,传入 指定类的构造方法
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

在这里插入图片描述
调用 org.springframework.beans.instantiateClass(Constructor ctor, Object... args)对获取到的指定类的构造方法使用反射实例化出对象信息。

整体流程图

Spring深入理解之IOC创建并获取Bean_第17张图片

你可能感兴趣的:(Spring框架相关)