[Spring 소스 코드 : FactoryBean II] 마지막으로 FactoryBean이 Bean 생성 프로세스를 사용자 정의하는 방법 이해

소개

에서 이전 기사 , 우리는 분석에 집중 흐름getObjectType의 메소드 의 FactoryBean을 , 그리고 마지막으로, 우리는 (IOrderService.calss)에 전달 클래스 타입하고 정의의 FactoryBean 서브 클래스 간의 관계를 설명하는 일반적인 흐름도를 그린 연결 방법, 즉 getBean (IOrderService.class)를 호출 하면 맨 아래 계층은 결국 factoryBean.getObjectType ()을 호출 합니다.

이 기사에서는 FactoryBean어떻게 Spring 컨테이너가 getObject ()호출하여 생성 된 Bean 을 관리 하도록 허용하는지 분석 한 다음 이전 기사의 후속 분석 (아래 참조)을 분석합니다.

DefaultListableBeanFactory # resolveNamedBean

이때 일부 변수 값은 다음과 같습니다.

  • requiredType : IOrderService.class
  • 후보 이름 : {“orderFactoryBean”}

후보 이름 배열의 길이가 1이기 때문에 getBean (beanName, requiredType, args) 메소드에 들어가고 ,이 메소드는 doGetBean 메소드를 호출하고 , doGetBean은 Spring 컨테이너 초기화의 매우 중요한 부분이지만 여기에서는 너무 많은 Spring Bean 수명을 분석하지 않습니다. 주기의 내용은이 기사에서 FactoryBean과 관련된 내용에만 집중합니다.

AbstractBeanFactory # doGetBean  (일부 관련없는 코드 생략)

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        //转换传入的BeanName的值,如&name变为name 以及别名(alias)的转换
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
        //调用getSingleton方法 从Spring容器中获取单例Bean,下面再具体分析此方法
        //这里的beanName为orderFactoryBean,获取到的是它对应的OrderFactoryBean实例(因为我们有添加@Component注解,spring容器中已创建该bean)
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {

            //这里是根据获取到的OrderFactoryBean实例本身去获取对象
            //注意这里传入了name和转换后的beanName
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

 DefaultSingletonBeanRegistry # getSingleton , Spring 컨테이너에서 싱글 톤 빈을 가져옵니다.

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //先从singletonObjects单例池(一级缓存)中获取Bean,singletonObjects是一个ConcurrentHashMap
        //key是beanName value是单例Bean		
        Object singletonObject = this.singletonObjects.get(beanName);
		//如果单例池中不存在,并且是当前正在创建中的Bean
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 加锁
			synchronized (this.singletonObjects) {
                //从二级缓存中获取早期的bean
				singletonObject = this.earlySingletonObjects.get(beanName);
                //如果没有获取到,并且允许提前引用相应的Bean(依赖注入)
				if (singletonObject == null && allowEarlyReference) {
                    //singletonFactories俗称三级缓存,key:beanName,value:ObjectFactory
                    // 这个ObjectFactory是一个函数式接口,所以支持Lambda表达式:() -> getEarlyBeanReference(beanName, mbd, bean)
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
                        //从ObjectFactory中获取Bean实例
						singletonObject = singletonFactory.getObject();
                        //放入earlySingletonObjects这个Map二级缓存中,依赖注入时用到
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

이 방법은 매우 중요하며 Spring 컨테이너의 3 단계 캐시를 포함합니다.

  • 레벨 1 캐시 : singletonObjects , 완전한 라이프 사이클을 거친 빈 객체 캐시합니다.
  • Second-level cache : earlySingletonObjects , singletonObjects보다 더 이른 것은 캐시 된 bean 객체가 초기 bean 객체임을 나타냅니다 (또는 : 캐시 이후에 얻은 프록시 객체AOP 를 위해 미리 원래 객체취함 ). 은 무슨 뜻인가요? Bean이 earlySingletonObjects에 들어가기 전에 Bean의 라이프 사이클이 완료되지 않았 음을 나타냅니다.
  • 3 단계 캐시 : singletonFactories , 캐시는 객체를 생성하는 데 사용되는 객체 팩토리를 나타내는 ObjectFactory입니다.

2 단계 캐시는 주로 Spring에서 순환 종속성을 해결하는 데 사용됩니다. SingletonFactories는 주로 AOP 이후 얻은 원본 객체와 프록시 객체를 생성하는 데 사용됩니다. 자세한 내용은 "[인터뷰 질문] 마지막으로 누군가가 Spring의 순환 종속성을 명확하게 설명 할 수 있습니다. " , 잘 작성되었습니다.

아래 주제로 돌아가서 AbstractBeanFactorygetObjectForBeanInstance 를 분석해 보겠습니다.

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // 如果传进来的OrderFactoryBean不属于FactoryBean的实例,则直接返回当前实例(表示它是普通的bean)
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}
        
        // 如果是FactoryBean子类bean
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {// 缓存中获取
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
            //如果能走到这里来,说明这个bean实例是FactoryBean类型的
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 从该方法名字看出:从FactoryBean中获取对象,下面再具体分析
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

分析FactoryBeanRegistrySupport #  getObjectFromFactoryBean

	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {

        //FactoryBean类型的实例是否单例
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
                //从缓存中获取
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {

                    //缓存获取不到,则调用doGetObjectFromFactoryBean方法从FactoryBean中获取bean对象
                    //这里是调用的FactoryBean的getObject方法来获取的,具体看这一步
					object = doGetObjectFromFactoryBean(factory, beanName);
					// 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);

                    //如果上一步的缓存中获取到了,则用缓存中的替代FactoryBean中获取的bean
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
                                //调用BeanPostProcessor中的postProcessAfterInitialization方法进行处理
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
                            //添加到factoryBeanObjectCache中缓存,key为beanName
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
            //FactoryBean的实例非单例情况
			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;
		}
	}

doGetObjectFromFactoryBean 분석 , 여기 객체를 얻기 위해 호출 된 FactoryBean의 getObject 메소드 가 있습니다.

	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
                // 终于看到了FactoryBean中的getObject(),真相大白
				object = factory.getObject();
			}
		}

		return object;
	}

대략적인 순서도 ( 인용 )

요약하자면

대략적인 과정 : 우리가 전달한 클래스 유형에 따라 Spring 컨테이너의 모든 BeanName을 루프 한 다음 beanName에 따라 해당 Bean 인스턴스를 획득하고 획득 한 Bean 인스턴스가 FactoryBean 유형의 Bean인지 확인합니다. 그렇다면 FactoyBean의 getObjectType 메소드를 호출합니다. 클래스를 획득하고 획득 한 클래스를 전달 된 클래스와 일치시키고 일치하는 경우이 beanName과 전달 된 클래스 간의 매핑 관계를 설정합니다. 그런 다음 beanName에 따라 Spring 컨테이너에서 해당 FactoryBean 인스턴스 빈을 얻고 FactoryBean의 getObject 메서드를 호출하여 메서드에서 사용자 정의 빈을 얻습니다.

참조 : https://conan.blog.csdn.net/article/details/79588391

역사상 가장 강력한 Tomcat8 성능 최적화

알리바바는 왜 90 초 안에 100 억을 저항 할 수 있습니까? -서버 측 동시성이 높은 분산 아키텍처의 진화

B2B 전자 상거래 플랫폼 --ChinaPay UnionPay 전자 결제 기능

Zookeeper 분산 잠금을 배우고 면접관이 감탄하면서 당신을 볼 수 있도록하십시오

SpringCloud 전자 상거래 스파이크 마이크로 서비스 -Redisson 분산 잠금 솔루션

더 많은 좋은 기사를 확인하고 공식 계정을 입력하십시오.

깊고 충만한 공개 계정 0.0

추천

출처blog.csdn.net/a1036645146/article/details/111736852