Spring源码分析之FactoryBean方式注入bean

factorybean注解方式注入 1、factorybean注解模式注入 factorybean即工厂bean,可以让开发者干预bean的创建过程。直接上代码 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=... 阅读详情

1.前言

Demo中的beanFactory的引入,代码如下:

配置类:
@Configuration
public class Cap6MainConfig {
    @Bean("testFactoryBean")  
    public TestFactoryBean testFactoryBean(){
        return new TestFactoryBean();
    }

}

TestFactoryBean类:
import cn.enjoy.cap6.Pig;
import org.springframework.beans.factory.FactoryBean;

public class TestFactoryBean implements FactoryBean<Pig> {
    public Pig getObject() throws Exception {
        return new Pig();
    }

    public Class<?> getObjectType() {
        return Pig.class;
    }

    public boolean isSingleton() {
        return true;  //是一个单例的bean
    }
}

测试类:
public class Cap6Test {
    @Test
    public void test() {
        AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap6MainConfig.class); //解析配置文件
        Object bean1 = app.getBean("testFactoryBean");
        Object bean2 = app.getBean("testFactoryBean");
        System.out.println("bean的类型="+bean1.getClass()); //Pig实例(1)
        System.out.println(bean1 == bean2);
        Object bean3 = app.getBean("&testFactoryBean");//取的是testFactoryBean实例,加了特殊字符(2)
    }
}

2.问题描述

为什么上述代码块中的(1)和(2)处的实例是不一样的?

3.解惑一

进入debug模式,追踪app.getBean方法,如下:

@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();  //上下文中的BeanFactory的激活断言
		return getBeanFactory().getBean(name);//追踪如下代码块 ①
	}
①:
	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);   name: "testFactoryBean"
	}
继续追踪-->②
②
@SuppressWarnings("unchecked")
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		final String beanName = transformedBeanName(name);//获取去掉前缀的beanName,详见3.1
		Object bean; //存放返回对象,懒汉单例模式

		// Eagerly check singleton cache for manually registered singletons.
        //在单例缓存中检查手动注册的单例
		Object sharedInstance = getSingleton(beanName); //详见3.2,beanName=“testbeanFactory”
		if (sharedInstance != null && args == null) { //为true
			if (logger.isTraceEnabled()) {  //日志,直接忽略
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//详见3.3所示
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

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

			try {
				final 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) {
					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);
						}
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				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);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final 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);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						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",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

3.1 transformedBeanName(String name)方法详解

protected String transformedBeanName(String name) {
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}
//canonicalName(BeanFactoryUtils.transformedBeanName(name))见3.1.2

public static String transformedBeanName(String name) {
        //非空检查
		Assert.notNull(name, "'name' must not be null");
        //判断是否不是以&前缀开头,在本例中返回为true
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
       //如果是以“&”前缀开头,这里使用到lambda表达式,假设此时的name=&testBeanFactory
       //下面这个函数的逻辑为:
       //transformedBeanNameCache是一个在Spring中申明的ConcurrentHashMap,以下简称Map
       //如果map中name对应的值不为空,直接返回
       //如果为空,则根据上述的映射函数进行计算,并put进入Map中
       //总而言之,该Map中存储的都是没有&开头的名字

		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());//参数为1
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
           //该lambda表达式的意思是:去掉name之前所有的“&”前缀,直到不以&开头
			return beanName;
		});
	}
//分析transformedBeanNameCache.computeIfAbsent()方法于3.1.1

3.1.1 computeIfAbsent方法详解

Map.class
//如果指定的key没有与value进行关联(或者映射到null),则试图通过给定的映射函数计算其值,并及那个该计算的结果映射到该map中,除非其值为null
default V computeIfAbsent(K key,
            Function<? super K, ? extends V> mappingFunction) { //假设为key:&testBeanFactory
        //非空检查
        Objects.requireNonNull(mappingFunction);
        V v; //申明v
        if ((v = get(key)) == null) { //判断key对应的value值是否为空
            V newValue;  //申明新值
            if ((newValue = mappingFunction.apply(key)) != null) { //通过新的映射关系获得newValue值
                put(key, newValue); //newValue不为null,则插入map并返回
                return newValue;
            }
        }

        return v;  //在key在map中映射的value不为空,则返回value 
    }

3.1.2 canonicalName方法详解

//确定原始名称,将别名解析为规范名称
public String canonicalName(String name) {   //name="testFactoryBean"
        
		String canonicalName = name;
		// Handle aliasing... 处理别名
		String resolvedName;
        //循环,resolvedName为null,跳出循环,别名有待研究,里面的逻辑目前还不明确
        //按照以下循环逻辑,别名中存的映射关系:a-->b--->c....x--->null,作用是取出x
		do {
			resolvedName = this.aliasMap.get(canonicalName); //取出aliasMap中的canonicalName对应的值
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;  //当前输出的是就是name值
	}

3.2 getSingleton方法详解

@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) { //参数:“testBeanFactory” true
        //singletonObjects是单例的缓存池,为一个hashMap的结构
		Object singletonObject = this.singletonObjects.get(beanName); //取值,本例中该值不为null
        //isSingletonCurrentlyInCreation方法底层,是判断一个set集合(存放正在创建的bean的集合)中是否包含beanName
        //缓存为空且该set集合中包含beanName,向下执行
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            //如果上面的singletonObjects缓存池中找不到,则去早期的缓存池中寻找
			synchronized (this.singletonObjects) {  //同步代码块
                //从earlySingletonObjects这个存放早期单例对象的hashMap中取值
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;  //直接返回singletonObjects单例的缓存池中的值,其实是一个TestBeanFactory类的实例对象
	}

3.3 getObjectForBeanInstance(sharedInstance, name, beanName, null)方法详解

/**
	 * Overridden in order to implicitly register the currently created bean as
	 * dependent on further beans getting programmatically retrieved during a
	 * {@link Supplier} callback.
	 * @since 5.0
	 * @see #obtainFromSupplier
     //重写,以隐式注册当前创建的bean,使其依赖于在回调期间以编程方式检索的其他bean
	 */
	@Override
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		String currentlyCreatedBean = this.currentlyCreatedBean.get(); //详见3.3.1,结果返回为null
		if (currentlyCreatedBean != null) { //不进入
			registerDependentBean(beanName, currentlyCreatedBean);
		}

		return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd); //详见3.3.2
	}


3.3.1 this.currentlyCreatedBean.get()方法详解

 /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     * 返回当前线程对此thread-local变量的拷贝
       //如果当前线程对于此变量无值,则该值将会被第一次初始化为{@link #initialValue}反射方法返回  
       //的值
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread(); //获取当前线程
        ThreadLocalMap map = getMap(t);  //获取与当前线程的ThreadLocalMap静态类对象
        //ThreadLocalMap是一个静态类,ThreadLocalMap is a customized hash map suitable only 
        // for maintaining thread local values.该结构中存在一个静态的Entry对象
        //k---ThreadLocal    v---Object
        if (map != null) { //map不为null,向下执行
            ThreadLocalMap.Entry e = map.getEntry(this); //this:当前的ThreadLocal对象
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value; //获得entry中的当前ThreadLocal对象对应的value值
                return result; //返回为null
            }
        }
        return setInitialValue();
    }

3.3.2  super.getObjectForBeanInstance(beanInstance, name, beanName, mbd)方法详解

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name)) {// //是否以“&”前缀开头,否
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		if (!(beanInstance instanceof FactoryBean)) { //false
			return beanInstance;
		}
		

		Object object = null;
		if (mbd != null) { //false
			mbd.isFactoryBean = true;
		}
		else {
			//在缓存中取beanname为testFactoryBean的value值,FactoryBean对象目前还没有创建,所以输出为nulL
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) { //true
				//containsBeanDefinition就是在判断spring底层的beanDifinitionMap中是否包含了beanName的键值
				//在spring的register阶段,该Map中就已经被赋值,故而包含
				mbd = getMergedLocalBeanDefinition(beanName); //包装TestFactoryBean为RootBeanDifinition
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());//false
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);//Pig@xxx,详见下
		}
		return object;//Pig@xxx
	}

以上内容解释了第一个问题,对于第二个问题解释如下(当getBean方法中传入的字符串是“&xxx”的时候,程序获得的对象是TestFactoryBean实例bean)

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		//factory:TestFactory@xxx  beanName:testFactoryBean shouldPostProcess:true
		//containsSingleton()判断singletonObject这个Map中是否包含beanName这个键值,非懒加载的单例对象在Spring容器初始化的时候就创建
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) { //同步代码块
				Object object = this.factoryBeanObjectCache.get(beanName); //取出为null
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);//Pig@xxx,详见下代码块
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);//取出为null
					if (alreadyThere != null) {//false
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {//true
							if (isSingletonCurrentlyInCreation(beanName)) {//false
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							//面向切片编程的思想
							//单例bean创建的回调,底层是一个异常,可以忽略
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);//object:Pig@xxx
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								//单例创建之后的回调,底层也是一个异常信息,可忽略
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {//true
							this.factoryBeanObjectCache.put(beanName, object);//向缓存中存入数据key:testFactoryBean  value:Pig@xxx
						}
					}
				}
				return object; //返回Pig@xxx
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
		Object object;
		try {
			if (System.getSecurityManager() != null) { //false 
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				object = factory.getObject(); //调用上文中自定义的TestBeanFactory中的getObject方法,返回Pig@xxx
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) { //false
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object; //返回Pig@xxx
	}

 

4.解惑二

分析过程类似于解惑一中所示,这里将重要的方法描述下:

4.1 doGetBean方法追踪

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//name:&testFactoryBean  requiredType:null args:null   typeCheckOnly:false
		String beanName = transformedBeanName(name);//如果有&前缀,去掉获得,beanName:testFactoryBean
		Object bean; //申明返回值 bean:null

		// Eagerly check singleton cache for manually registered singletons.
		//sharedInstance:TestFactoryBean@xxx 
		Object sharedInstance = getSingleton(beanName);//详见4.2
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//返回TestFactoryBean@xxx,详见4.3
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

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

			try {
				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) {
					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);
						}
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				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);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					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);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						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",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		//false 
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;//返回TestFactoryBean@xxx 
	}

4.2  getSingleton(String beanName)方法分析

@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}
--->

@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		////singletonObjects为一个单例的concurrentHashMap获取单例对象,其中存放了所有已经实例化好的单例bean对象
		//beanName这个key对应的value值为一个TestFactoryBean实例bean,记作TestFactoryBean@xxx
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { //false
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								singletonObject = singletonFactory.getObject();
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;//返回TestFactoryBean@xxx
	}

4.3  getObjectForBeanInstance方法分析

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
         //beanInstance:TestFactoryBean@xxx name:&testFactoryBean  beanName:testFactoryBean mbd:null
		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		//true
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {  //false
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) { //false
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) { //false
				mbd.isFactoryBean = true;
			}
			return beanInstance; //返回TestFactoryBean@xxx
		}

 

【QGIS】PyCharm集成pyqgis的processing工具箱:环境配置与初始化实战 本文详细介绍了如何在PyCharm中配置QGIS的Python环境并成功集成其强大的Processing工具箱。文章核心解决了独立环境下导入processing模块失败、算法无法调用等常见难题,通过手动添加插件路径和执行关键初始化步骤,实现了在PyCharm中丝滑调用QGIS地理处理算法,从而将复杂的空间分析流程自动化。 阅读详情

相关推荐

新手必看:SMIC 0.18um PDK安装保姆级教程(附Cadence IC617环境配置)

本文提供SMIC 0.18um PDK在Cadence IC617环境下的详细安装教程,涵盖环境准备、文件解压、安装脚本运行、环境变量配置及Cadence集成验证等关键步骤,特别针对初学者常见问题提供解决方案,助力快速掌握芯片设计工具配置。

weixin_30522183的博客 491

Spring注解驱动开发(七):利用FactoryBean向容器中注入组件

利用 @ComponentScan+@Component 向容器中注入组件 (专栏第一篇文章讲述)利用 @Configuration+@Bean 向容器中注入组件 (专栏第二篇文章讲述)利用 @Import 向容器中注入组件利用 @Import 向容器中注入组件 (专栏第三篇文章讲述)在本篇文章中,我会向你讲述如何利用FactoryBean接口向Spring容器中注册BeanFactoryBean 接口的基本用啊FactoryBean的源码分析。

城南花已开的博客 725

微信DAT图片恢复全攻略:从文件定位到批量解密(附最新路径变化)

本文提供了一份详尽的微信DAT图片恢复指南,涵盖新旧版本文件路径变化解析、DAT文件定位方法以及批量解密操作步骤。针对微信图片加密存储为DAT格式的痛点,文章介绍了高效易用的图形化解密工具,帮助用户将加密文件快速还原为JPG、PNG等可查看格式,并强调了数据安全与隐私保护的重要性。

p4q5r6s7t的博客 743

【Spring注解系列06】FactoryBean注入对象用法

使用Spring提供的 FactoryBean(工厂Bean); 1)、默认获取到的是工厂bean调用getObject创建的对象 2)、要获取工厂Bean本身,我们需要给id前面加一个& &colorFactoryBean实例类与配置类 public class Color { } //创建一个Spring定义的FactoryBean public cla...

Java仗剑走天涯 3411

尝试使用CubeMX做stm32开发之九:SYS配置

参考《STM32中文参考手册_V10》,研究CubeMX中有关SYS的配置

Forster-C的博客 9420

Magisk如何针对性隐藏Root避免被检测

Magisk隐藏特征码有两种途径,一种是通过插件,一种是定制源码。插件的方式相对简单,但是使用范围也有限,好处是成本低好上手。定制源码难度大,成本高,好处是稳定,后续也好更新维护。

zhonglunshun的专栏 1万+

实力总结四类Bean注入Spring的方式

原创:微信公众号 【阿Q说代码】,欢迎分享,转载请保留出处。 文章目录xml 方式注解方式@Configuration + @Bean@ImportFactoryBeanBDRegistryPostProcessor源码实战 一提到Spring,大家最先想到的是啥?是AOP和IOC的两大特性?是Spring中Bean的初始化流程?还是基于Spring的Spring Cloud全家桶呢? 今天我们就从Spring的IOC特性入手,聊一聊Spring中把Bean注入Spring容器的几种方式。 我们先来简单.

阿Q的小窝 1611

如何在多 GPU 配置上运行 Unsloth:数据并行或模型并行

当工作负载受限于内存(模型或批次无法放入单张显卡)、或受限于计算且计算与通信比率较高时(即每块 GPU 的额外计算量超过同步参数的开销,如在 DDP 中,或超过传递激活值的开销,如在模型并行中),多 GPU 配置才开始显现优势。在松散连接的显卡上(尤其是 PCIe 版本的 H100 或 A100),额外的设备间数据传输会导致性能显著低于单 GPU 运行。让我们厘清概念,明确说明如何通过模型并行(将模型拆分到多个 GPU)或数据并行(在每个 GPU 上复制模型)来跨多 GPU 运行 Unsloth。

人工智能领域专家 645

Spring 与组件注入相关之 FactoryBean

前言: 前面已经介绍了十好几个与 spring 组件注入相关的注解,这里介绍最后一种组件注入方式(并不是通过注解,而是通过一个工厂 Bean ~ FactoryBean)。 简介: 关于 FactoryBean,可以自行查看源码相关注释。虽然是英文的,但是大致能看懂(本人水平有限,就不进行翻译了,而且有些翻译出来也觉得怪怪的 …)。此外,这里还引出了一个设计模式:工厂设计模式(这些人太厉害了~~)...

demon_2018的博客 648

电路设计仿真软件:Mentor Graphics_(1).MentorGraphics电路设计仿真软件概述

菜单栏:包含文件、编辑、视图、工具等菜单。工具栏:提供常用的工具按钮,如打开、保存、仿真等。原理图编辑区:用于绘制电路原理图。元件库:包含各种电路元件,支持拖拽操作。属性面板:显示选中元件的属性,可以进行参数设置。仿真控制区:用于设置仿真参数和控制仿真过程。输出窗口:显示仿真结果和日志信息。打开模型编辑器:点击“工具”菜单,选择“模型编辑器”。选择模型类型:在模型编辑器中选择模型类型,如SPICE模型。输入模型参数:根据需要输入模型的参数,如电阻值、电容值等。保存模型。

kkchenjj的博客 1924

AI Agent智能体在Android开发中的应用

本文探讨了AIAgent(智能代理体)在Android开发中的应用,涵盖技术原理、实践案例与未来趋势。AIAgent通过机器学习、自然语言处理等技术实现代码生成、测试自动化及性能优化,显著提升开发效率。例如,强化学习模型可优化APP响应时间(公式:$\text{响应时间}=f(\text{负载},\text{资源})$),自动化测试覆盖率提升至95%。

郑伟强dev的专栏 124

讲解 Spring 实例化的不同方式及相关生命周期源码剖析

该篇博文,先介绍了 BeanDefinition 接口以及与它子类之间的关系,主要分析的是在 Spring 中不同的实例化方式,如:FactoryBean、FactoryMethod、Supplier、自定义 BPP 接口实现类、反射注入,反射注入是 Spring 中比较核心的,它一般可以通过无参构造、有参构造去注入 Bean 实例;最后,MethodOverrides 此属性虽然在工作中很少应用,但我们应该要知道此【单例 Bean 引用原型 Bean 问题】问题的解决方案,希望博文能够帮助你快速的理解

vnjohn 博主 > 主线分享后端领域业务设计知识、源码思想、架构设计 2672

ThingsBoard-阿里云短信规则节点

由于Thingsboard平台国内只支持短信服务,那我们运维人员去及时接收邮箱肯定是没有短信来的方便的,在这基础上,需要自己从规则链入手,自定义一个支持阿里云短信服务的规则节点。

weixin_67440240的博客 2094

Spring系列--IOC详解

IOC笔记总结

qq_42194397的博客 3012

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Spring之【Bean的实例化方式】

介绍Spring中几种实例化Bean的方式

weixin_43945238的博客 1470

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Spring生命周期Bean初始化过程详解

Spring声明周期Bean初始化过程详解Spring 容器初始化Spring Bean初始化BeanFactory和FactoryBean源码分析Bean的实例化preInstantiateSingletonsgetMergedLocalBeanDefinitiongetBean方法getObjectForBeanInstance例子分析@DependsOn Spring 容器初始化 在spring中,不管是以xml文件的方式配置的Bean还是以注解的方式进行配置,最后都会将单例Bean放入到Spring

JAVA技术爱好者 1万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Spring中FactoryBean的使用

本文主要介绍什么是FactoryBean技术?为什么使用FactoryBean?使用FactoryBean的好处?目前优秀的框架有哪些用到了FactoryBean? 1. FactoryBean的介绍: FactoryBean从字面意思上理解是工厂bean,他可以生成某一个类型Bean实例,它最大的一个作用是:可以让我们自定义Bean的创建过程。 一...

qq_35634181的博客 3284

所有Bean的父亲,解密Spring容器中的FactoryBean接口

文章目录一、前言二、FactoryBean概要三、使用层面:FactoryBean接口实现类四、源码解析:FactoryBean接口4.1 从spring启动开始4.2 getBean()4.2.1 isFactoryBean()4.2.2 SmartFactoryBean接口(FactoryBean接口的唯一子接口)4.2.3 存在的问题:Spring启动默认不会将自定义FactoryBean接口的实现类作为bean,注入到spring ioc容器中4.3 doGetBean()4.3.1 doGetBe

毛毛的专栏 1185

Spring 源码分析衍生篇一:FactoryBean介绍

一、简介 一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean。但是在某些情况下,实例化bean 的过程比较复杂,在XML配置下如果按照传统的编码方式,则需要进行大量配置,灵活性受限,这时候Spring 提供了一个 org.springframework.beans.factory.FactoryBean 的工厂类接口。可以通过该接口定制实例化bean 的逻辑...

猫吻鱼的博客 2690

Spring FactoryBean原理与应用全解析

FactoryBean是Spring框架中用于封装复杂对象创建逻辑的核心接口,采用工厂模式实现Bean的延迟创建与定制化初始化。其技术原理通过getObject()方法动态生成目标对象,与普通Bean的差异体现在容器处理流程和依赖注入方式上。在工程实践中,FactoryBean广泛应用于ORM框架集成(如MyBatis的SqlSessionFactory)、动态代理生成(AOP实现)以及条件化Bean装配等场景。通过实现SmartFactoryBean接口可进一步优化初始化策略,结合对象池技术能有效管理资源

weixin_30660027的博客 305

【Spring源码系列】——彻底搞懂FactoryBean

在上篇博客中【源码Spring系列】——彻底搞懂BeanFactory和FactoryBean不同讲解了两者的不同,先确定两者的作用并不一样,本文主要讲解Spring是怎样从FactoryBean获取我们自己创建的Bean实例。

漫漫长途,终有回转;余味苦涩,终有回甘 736

Spring-FactoryBean解析

Spring-FactoryBean解析

weixin_45370502的博客 943

Spring 中注入 Bean 的各种骚操作做

内容来自【自学星球】欢迎大家来了解我的星球,和星主(也就是我)一起学习 Java ,深入 Java 体系中的所有技术。我给自己定的时间是一年,无论结果如何,必定能给星球中的各位带来点东西。Spring中的世界,一切皆 Bean,那么就先介绍多种向 Spring 中添加 Bean 的方式。

技术分享、唠嗑水文、如有不周、还望海涵 884

Spring源码分析十四:FactoryBean深度解析

Spring源码分析十四:FactoryBean深度解析

我从不打没有准备的仗! 9466

spring源码分析之bean的加载

这篇博文主要针对getBean()方法来介绍bean加载的相关原理,其中涉及到循环依赖解决,FactoryBean获取对象,类型转换等知识点,通过这篇博文读者可以概览bean的加载流程,读者可以对spring源码解析有清晰的认识

liushangzaibeijing的博客 6万+

Spring中FactoryBean的BeanName解读

这里写目录标题简介结果演示环境结论源码分析1、转变BeanName2、从容器中获取BeanName对应的对象3、核心方法getObjectForBeanInstance4、判断逻辑1、先判断`name`是否为空,是否是`&`开头2、 接下来继续走逻辑,通过BeanName从`某个`缓存中获取对象3、如果缓存取不到就进行创建对象处理4、创建对象过程5、加入到Bean对象`factoryBeanObjectCache`容器中小结DEBUG查看容器对象信息factoryBeanObjectCache容器B

a760352276的博客 3463
上一篇: Spring容器启动之注册类bean的注入
下一篇: 踩坑之Spring源码工程构建中gradle下载过慢而无法构建成功
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值