Spring Bean是如何初始化的详解

目录
  • 前言
  • 三级缓存
  • doGetBean
    • createBean
    • doCreateBean
    • instantiateBean
    • instantiate
    • instantiateClass
  • 注入
    • AutowiredAnnotationBeanPostProcessor分析
    • postProcessProperties 如何实现bean注入的
  • 总结

前言

做Java都有很多年了,一直有一个疑惑: Spring 如何初始化bean,怎么调用反射实例化对象的,自己动手来解除这个疑惑。 过去我认为spring bean对象实例化一直都是由BeanPostProcessor接口实现类去做的,我就是不知道具体那个实现类,下面就去验证下这个猜想。

三级缓存

为什么面试官特别喜欢问创建bean的三级缓存,主要是因为bean创建都是伴随着三级缓存之间的转换完成的,对象不同状态分别存在不同缓存中,下面我会在分析代码时,顺便支持对象如何在缓存中流转的。 先了解下spring 三级缓存。

    /** 一级缓存 用于存放完全可以使用单例bean,也就是初始化完成并且注入所有依赖 */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** 二级缓存 过早暴露单例对象,此时bean刚刚完成初始化,未完成属性注入和执行 init 方法 */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

	/** 三级缓存  装载创建bean的工厂对象 */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)

三级缓存主要作用: 创建对象ObjectFactory首先放入三级换缓存中,当调用getObject 创建实例时,会将创建好对象加入二级缓存中,并且删除三级中缓存,当对象已经完成初始化方法和属性注入,再将缓存添加到一级缓存中,并且删除二级缓存。

doGetBean

从源头开始找,所有spring bean 初始化都是由AbstractBeanFactory.doGetBean方法实现的。下面我将源码减除臃肿部分,贴出来。

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
        //name 前缀处理  beanFactory beanName 带有&开头
		String beanName = transformedBeanName(name);
		Object beanInstance;
        //从三级缓存去取bean,三级中都没有则返回null,说明对象还没有创建
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) { //如果缓存中bean 是FactoryBean实例,要通过接口获取到实际bean
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		else {
             //判断bean对象标记是否正在创建中,如果正在创建中则不应该继续下去,出现依赖循环就会出现这个错误
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
			BeanFactory parentBeanFactory = getParentBeanFactory();
            // 检查父容器是否存在,尝试从父容器中获取
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) { //缓存中标记beanName 正在被创建
				markBeanAsCreated(beanName);
			}
			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
					.tag("beanName", name);
			try {
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {  //bean 中@DependsOn 信息,用于标记bean之间初始化顺序,优先创建@DependsOn   中bean
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

			     //创建单例对象
				if (mbd.isSingleton()) { //重点就在这里实例化对象  ,getSingleton 就是在这里将创建完成对象加入到一级缓存中
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex)
							destroySingleton(beanName);
							throw ex;
						}
					});
                    //如果生成bean 是FactoryBean ,再获取真正的对象
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
                //作用域 = prototype,因为不会放入缓存中,每次获取都要重新创建
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else { // session request 这些作用域,由作用域容器去管理这些对象
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					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, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
				beanCreation.end();
			}
		}
                //返回初始化成功的对象,一个对象初始化就这样完成的了
		return adaptBeanInstance(name, beanInstance, requiredType);
	}

大概总结一下上面代码流程:

  • 先从三级缓存中获取,如果缓存中都没有。再去判断是否存在父容器,从父容器中获取。没有正式进入bean 初始化流程,先根据beanName 获取到RootBeanDefinition,bean类元信息、先处理dependsOn中bean,保证bean依赖的创建顺序,下面会说明org.springframework.context.annotation.@DependsOn这个注解。下一步按照不同scope 进行bean 对象初始化。初始化流程就是这样,我们将目光放在单例bean 如何实例化,集中关注AbstractAutowireCapableBeanFactory.createBean 获取注册一个单例对象

@DependsOn 注解意思是实例化某个对象依赖于某一个实例化,但是不需要持有这个实例对象。比如bean A上 需要依赖bean b才能实例化,但是bean b 不需要作为他的属性,常常用于不同实例实例化顺序标记。

看下getSingleton方法

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) { //标记bean 是否在销毁
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
				}
				catch (BeanCreationException ex) {
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject); //就是在这里删除二三级缓存,提交到一级缓存
				}
			}
			return singletonObject;
		}
	}
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

添加到一级缓存则说明bean已经完成实例化,可以正常使用了。下面看下如何进行实例化和属性注入的。

createBean

下面进入AbstractAutowireCapableBeanFactory.createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		RootBeanDefinition mbdToUse = mbd;
        //克隆一份mbd => mbdToUse
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                //通过BeanPostProcessors 增强返回一个代理对象,这个生成AOP的代理对象,使用多个BeanPostProcessors来处理
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
            // bean 对象实例化就这里实现
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

这里逻辑就比较简单了 ,克隆一份RootBeanDefinition用于初始化对象,resolveBeforeInstantiation 主要用于初始化代理对象情况,主要使用BeanPostProcessor子类InstantiationAwareBeanPostProcessor实现方法去实现对象初始化,并且在实例化成功后在调用后置方法进行对象依赖注入,这里可以看见此方法返回对象直接跳出方法栈,这里可以看出单例和代理对象还是有区别的。单例对象初始化就在doCreateBean 实现了

doCreateBean

下面就是AbstractAutowireCapableBeanFactory.doCreateBean非常接近对象如何实例化的了

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);  //这个就是实例化方法
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// 使用BeanDefinitionPostProcessors 对合并bean进行实例化
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// 这里就需要用到上面说的三级缓存知识了
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName)); //是否放入第三级缓存中
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); //将已经实例化的对象加入到第三级缓存 singletonFactories
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper); //对属性进入注入,下面会具体分析的
			exposedObject = initializeBean(beanName, exposedObject, mbd); //执行初始化方法,或者注入Aware 接口bean
		}
		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);
			}
		}

		//下面代码省略
               //主要就是对设置了DisposableBean 接口销毁钩子方法处理
	}

这里代码主要分成三部分

  • 初始化实例,创建对象完成,并且添加到3级缓存。第3级缓存常常用于存储代理对象,因为有些类需要动态代理方法,需要生成代理对象,会委派给第三级缓存方法ObjectFactroy去实现的,普通对象如果不需要会直接返回。
  • 对实例化bean进行属性注入
  • 执行初始化方法,DisposableBean接口加入到disposableBeans容器中

instantiateBean

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		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());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {// 有实现Supplier 接口,由instanceSupplier.get() 方法创建实例
			return obtainFromSupplier(instanceSupplier, beanName);
		}

                //factoryName  使用工厂模式创建bean,调用工厂方法去创建,这个支持静态方法和factoryBean.invoke
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		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) {
                               //使用构造函数注入方式实例化
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
                               //实例化对象
				return instantiateBean(beanName, mbd);
			}
		}

		// 获取构造函数参数
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}

实例化方法instantiateBean最终会调用SimpleInstantiationStrategy.instantiate 进行实例化

instantiate

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);
					}
				}
			}
			return BeanUtils.instantiateClass(constructorToUse); //调用构造函数进行实例化
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

instantiateClass

	@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);
					}
				}
			}
			return BeanUtils.instantiateClass(constructorToUse);  //调用构造器进行初始化
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

这里要注意下先判断bean是否有方法重写的,没有则使用反射生成的构造器,有就使用gclib方式创建代理对象,具体实现方式就在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate,有兴趣同学可以去学习下。 到此一个简单bean实例化完成了。

注入

下面进入IOC另一个特点,bean注入,先从AbstractAutowireCapableBeanFactory.populateBean方法开始

	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
              //通过InstantiationAwareBeanPostProcessors.postProcessAfterInstantiation 如果返回true,目标实例内部的返回值会被populate,否则populate这个过程会被忽视
            //翻译说如果返回true可以执行字段注入 真的6666啊
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
                //获取注入方式分布有4种
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
            //依赖方式,模式都是没有类型检查,这种依赖方式一般都是xml 配置用得比较多,没有配置这里都是返回false
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); /

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);  //获取注解标注需要注入方法或者是字段,并且进行注入
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

小知识点: AutowireCapableBeanFactory.AUTOWIRE_NO 表明不会对当前Bean进行外部类的注入,常规使用@Autowire、@Resource 都是这类型 剩下三种都是通过xml 或者 AutowireCapableBeanFactory.autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) 进行设置autowireMode 。

根据上面代码可以知道主流程bean注入都是由InstantiationAwareBeanPostProcessor 进行处理的,简单说明接口方法

方法 描述
postProcessBeforeInitialization 方法是最 先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
postProcessAfterInitialization 方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行
postProcessPropertyValues 对bean属性值赋值后调用,对属性值的修改。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改
postProcessProperties Bean属性赋值就是调用这个方法的

InstantiationAwareBeanPostProcessor 接口实现类主要分3个

  • ConfigurationClassPostProcessor:看类名就知道处理@Configuration实例化,并没有属性注入逻辑,不详讲略过。
  • CommonAnnotationBeanPostProcessor:这个类就是实现bean注入,但是是实现JSR-250 注解、@Resource,@EJB、@WebServiceRef,@WebServiceContext,@PostConstrusct、@PreDestory这些注解实现。
  • AutowiredAnnotationBeanPostProcessor:实现 @Autowired、@Value注入,并且支持JSR-330's @Inject,主要分析这个类就可以知道bean 注入的。

AutowiredAnnotationBeanPostProcessor分析

	private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
	@SuppressWarnings("unchecked")
	public AutowiredAnnotationBeanPostProcessor() {
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

在初始化时就将支持注解加入集合中,再使用扫描器去扫描方法、构造器、字段,如果有这些注解就进行注入。

看下怎么判断是否需要注入的

	@Nullable
	private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
		MergedAnnotations annotations = MergedAnnotations.from(ao);
		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
			MergedAnnotation<?> annotation = annotations.get(type);
			if (annotation.isPresent()) {
				return annotation;
			}
		}
		return null;
	} 

AccessibleObject 是Method、Field、Constructor 父类。

postProcessProperties 如何实现bean注入的

	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
              //获取需要注入字段,方法
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			metadata.inject(bean, beanName, pvs); //注入
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}
       //下面就行获取InjectionMetadata
	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// 快速从缓存中获取,如果没有加锁去解析,然后在结果放入缓存中
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) { //双重检查
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}
  • InjectionMetadata 主要是集合bean需要被注入类型,因为已经解析过bean Class信息了,相当于解析结果装起来

看下如何去扫描方法、字段的

 	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
       //从给定注解中判断class 是否携带这个注解
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
            //遍历所有Field,找出扫描的注解,特意标注不支持static 修饰field
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
                     // 获取注解内 required 值
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                //获取方法上桥接方法,因为泛型类型擦除,要对桥接方法进行安全检查,防止在调用是出现异常
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
                //获取注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
               //方法安全检查
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (Modifier.isStatic(method.getModifiers())) { //不支持静态方法注入
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});
           // 这样写是为了后面加入排在队列前面,父类属性优先于子类
			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class); //这里写得很好,向上解析父类,直到是Object 为止

		return InjectionMetadata.forElements(elements, clazz);
	}

逻辑非常简单,就是根据给定注解去class获取指定的注解,从而获取到需要注入类型,但是几行简单的代码可以看出强大编码能力,学习了。 现在需要注入对象已经获取到,看如何注入吧

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			for (InjectedElement element : elementsToIterate) {
				element.inject(target, beanName, pvs);
			}
		}
	}

		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				try {
					value = resolvedCachedArgument(beanName, this.cachedFieldValue);
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Unexpected removal of target bean for cached argument -> re-resolve
					value = resolveFieldValue(field, bean, beanName);
				}
			}
			else {
				value = resolveFieldValue(field, bean, beanName);
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}

		private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
			DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
			desc.setContainingClass(bean.getClass());
			Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
			Assert.state(beanFactory != null, "No BeanFactory available");
			TypeConverter typeConverter = beanFactory.getTypeConverter(); //类型转换器
			Object value;
			try {
				value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
			}
			synchronized (this) {
				if (!this.cached) {
					Object cachedFieldValue = null;
					if (value != null || this.required) {
						cachedFieldValue = desc;
                        // 将注入关系添加到容器中,方便bean销毁时同步销毁
						registerDependentBeans(beanName, autowiredBeanNames);
						if (autowiredBeanNames.size() == 1) {
							String autowiredBeanName = autowiredBeanNames.iterator().next();
							if (beanFactory.containsBean(autowiredBeanName) &&
									beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { //这些都是为了缓存起来
								cachedFieldValue = new ShortcutDependencyDescriptor(
										desc, autowiredBeanName, field.getType());
							}
						}
					}
					this.cachedFieldValue = cachedFieldValue;
					this.cached = true;
				}
			}
			return value;
		}
	}

主要核心是如从缓存获取到需要注入类型实例在beanFactory.resolveDependency中 进入DefaultListableBeanFactory看下

	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
                        //懒加载  扫描@Lazy注解,返回一个代理对象
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

@Lazy 使用注解修饰bean 或者Class,在容器初始化化时不会立刻创建,只要需要使用bean才会创建的。 根据类型Optional、ObjectFactory、Provider,还有懒加载情景不同的处理,这些处理本质都是要调用doResolveDependency方法初始化对象,无论那种对象都要 获取原始对象然后再交给这些接口去包装增强。

	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
            //如果这个注入是通过构造器注入,可以从构造器解析缓存中去获取注入信息点
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class<?> type = descriptor.getDependencyType();
                     //尝试从注解中获取默认值   @Value  的value
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}
              //多种混合类型处理,stream、collection、Map Array 这些
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

                  //根据类型获取容器中bean名,返回map key就是bean名,value 初始从容器中获取对象,如果没有找到就会抛出异常了
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {  //出现一个类型,不同实例,可以根据@Primary, @Priority、属性名方式去配置
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {  //没有确定,抛出异常
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {  //这里其实就是从容器中获取实例,如果这时候没有初始化,就走上面初始化流程
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

这个方法简单做个总结,先是处理 @Value 情况,然后通过findAutowireCandidates 通过类型去容器中获取实例,如何实例还没有初始化,就会调用上面那个初始化过程,将初始化对象返回。根据注入类型进行相应处理,像stream、Collection,这些混合类型都是直接添加进去。如果出现了一个类型多个bean情况,这时就是就是@Primary、@Priority这些注解来判断或者根据属性名去和beanName匹配,最后将bean对象返回。 这里就简单看完一个bean初始化流程了。

总结

现在知道了Bean实例化是由一个策略模式,使用反射攻击类创建的,和BeanPostProcessor其实并没有太多关系的。像我刚开始学spring时,老师就说@Autowired 和@Resources向比较,基于类型和beanName进行注入的,这样说不完全正确的。他是通过类型去获取bean,如果出现一个类型有多个beanName,才通过bean和属性名进行注入。使用这么多年Spring了,从来没有使用过@DependsOn、@Primary、@Priority、@Lookup如果不看源码还不知道有这个特性呢。看完整个源码,对bean生命周期有了比较清晰 bean实例化-> 属性注入-> 执行初始化方法-> 加入spring容器

到此这篇关于Spring Bean是如何初始化的文章就介绍到这了,更多相关Spring Bean初始化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈spring容器中bean的初始化

    当我们在spring容器中添加一个bean时,如果没有指明它的scope属性,则默认是singleton,也就是单例的. 例如先声明一个bean: public class People { private String name; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String get

  • 详解Spring 中如何控制2个bean中的初始化顺序

    开发过程中有这样一个场景,2个 bean 初始化逻辑中有依赖关系,需要控制二者的初始化顺序.实现方式可以有多种,本文结合目前对 Spring 的理解,尝试列出几种思路. 场景 假设A,B两个 bean 都需要在初始化的时候从本地磁盘读取文件,其中B加载的文件,依赖A中加载的全局配置文件中配置的路径,所以需要A先于B初始化,此外A中的配置改变后也需要触发B的重新加载逻辑,所以A,B需要注入彼此. 对于下面的模型,问题简化为:我们需要initA()先于initB()得到执行. @Service pu

  • Spring Bean的初始化和销毁实例详解

    本文实例讲述了Spring Bean的初始化和销毁.分享给大家供大家参考,具体如下: 一 点睛 在开发过程中,经常遇到在Bean使用之前或者之后做一些必要的操作,Spring对Bean的生命周期的操作提供了支持. 1 Java配置方式:使用@Bean的initMethod和destroyMethod. 2 注解方式:利用JSR-250的@PostConstruct和@PreDestroy. 二 实战 1 增加JSR250支持 <dependency> <groupId>javax.

  • SpringBoot中的Bean的初始化与销毁顺序解析

    我今天学习到SpringBoot里面自定义Bean的初始化与销毁方法 我先总结一下我学到的四种方法: 方法一: 指定init-method 和 destory-method 方法二: 通过让 Bean 实现 InitializingBean 接口,定义初始化逻辑 DisposableBean 接口,定义销毁逻辑 方法三: 用 @PostConstruct,在 Bean 创建完成并且赋值完成后,执行该注解标注的方法 @PreDestroy,在容器销毁 Bean 之前,执行该注解标注的方法 方法四:

  • Spring Bean初始化及销毁多种实现方式

    这篇文章主要介绍了Spring Bean初始化及销毁多种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.前言 日常开发过程有时需要在应用启动之后加载某些资源,或者在应用关闭之前释放资源.Spring 框架提供相关功能,围绕 Spring Bean 生命周期,可以在 Bean 创建过程初始化资源,以及销毁 Bean 过程释放资源.Spring 提供多种不同的方式初始化/销毁 Bean,如果同时使用这几种方式,Spring 如何处理这几

  • Spring中bean的初始化和销毁几种实现方式详解

    Bean的生命周期 : 创建bean对象 – 属性赋值 – 初始化方法调用前的操作 – 初始化方法 – 初始化方法调用后的操作 – --- 销毁前操作 – 销毁方法的调用. [1]init-method和destroy-method 自定义初始化方法和销毁方法两种方式:xml配置和注解. ① xml配置 <bean id="person" class="com.core.Person" scope="singleton" init-meth

  • Spring Bean是如何初始化的详解

    目录 前言 三级缓存 doGetBean createBean doCreateBean instantiateBean instantiate instantiateClass 注入 AutowiredAnnotationBeanPostProcessor分析 postProcessProperties 如何实现bean注入的 总结 前言 做Java都有很多年了,一直有一个疑惑: Spring 如何初始化bean,怎么调用反射实例化对象的,自己动手来解除这个疑惑. 过去我认为spring be

  • Spring bean 四种注入方式详解

    目录 一.Set方式注入 pojo层: 1.xml 文件 test测试 二.构造函数方式注入 pojo层 2.xml文件 test测试 三.注解注入 pojo层 3.xml文件 test测试 四.JavaConfig 方式注入 pojo层 JavaConfig 类 xml文件 扫描包 测试: 五.Service层注入详解 service serviceImpl xml配置文件 总结 一.Set方式注入 pojo层: /** * @Author: crush * @Date: 2021-06-17

  • Java Spring Bean的生命周期管理详解

    目录 Spring Bean的生命周期管理 一.Spring Bean的生命周期 二.通过@Bean的参数(initMethod ,destroyMethod)指定Bean的初始化和销毁方法 1.项目结构 2.Person 3.Bean注册配置类(单实例) 4.测试类 5.测试结果 6.Bean注册配置类(多实例) 7.测试结果 三.Bean实现接口InitializingBean, DisposableBean 1.Person 2.Bean注册配置类 3.测试结果 四.通过注解@PostCo

  • Spring Bean三种注入方式详解

    在Spring容器中为一个bean配置依赖注入有三种方式: 使用属性的setter方法注入  这是最常用的方式: 使用构造器注入: 使用Filed注入(用于注解方式). Field注入是最常见的一种方式,可以采用 @Autowired 对Bean类的接口进行初始化,代码如下 @ContextConfiguration({"/META-INF/spring/amazing-base.xml"}) @RunWith(SpringJUnit4ClassRunner.class) public

  • Spring Bean常用依赖注入方式详解

    一般而言,Spring的依赖注入有三种:构造器注入.setter注入以及接口注入.本文主要讲构造器注入与setter注入. 1.构造器注入 为了让Spring完成构造器注入,我们需要去描述具体的类.构造方法并设置构造方法的对应参数. 代码如下: public class Role { private Long id; private String roleName; private String note; public Long getId() { return id; } public vo

  • Spring为IOC容器注入Bean的五种方式详解

    这篇文章主要介绍了Spring为IOC容器注入Bean的五种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.class}) @Configuration @Import({Color.class,Red.class,MyImportSelector

  • Spring中Bean的命名方式代码详解

    本文主要描述的是关于spring中bean的命名方式,通过简单实例向大家介绍了六种方式,具体如下. 一般情况下,在配置一个Bean时需要为其指定一个id属性作为bean的名称.id在IoC容器中必须是唯一的,此外id的命名需要满足xml对id的命名规范. 在实际情况中,id命名约束并不会给我们带来影响.但是如果用户确实希望用到一些特殊字符来对bean进行命名,那么可以使用bean的name属性来进行命名,name属性没有字符上的限制,几乎可以使用任何字符. 每个Bean可以有一个或多个id,我们

  • Spring实例化bean的四种方式详解

    目录 一.bean实例化——构造方法(常用) 二.bean实例化——静态工厂(了解) 三.bean实例化——实例工厂(了解) 四.bean实例化——FactoryBean(实用) 一.bean实例化——构造方法(常用) bean本质上就是对象,创建bean使用构造方法完成 BookDao接口: public interface BookDao { public void save(); } BookDaoImpl实现类,利用构造方式提供可访问的构造方法,输出相应字符串: import com.i

  • Spring注解@Configuration与@Bean注册组件的使用详解

    目录 原始Spring开发 Person.java pom.xml bean.xml PersonTest.java 注解Spring开发 原始Spring开发 Person.java 准备Person.java类: package com.jektong.spring; public class Person { private String name; private int age; public Person() { super(); } public Person(String nam

  • Spring中bean集合注入的方法详解

    目录 Map注入 List注入 Set注入 数组注入 应用 哈喽大家好啊,我是Hydra. Spring作为项目中不可缺少的底层框架,提供的最基础的功能就是bean的管理了.bean的注入相信大家都比较熟悉了,但是有几种不太常用到的集合注入方式,可能有的同学会不太了解,今天我们就通过实例看看它的使用. 首先,声明一个接口: public interface UserDao { String getName(); } 然后定义两个类来分别实现这个接口,并通过@Component注解把bean放入s

随机推荐