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

소개

우리의 일상적인 JavaWeb 개발에서 우리는 FactoryBean 클래스를 보거나 사용 했어야했습니다. 많은 사람들 그것과 BeanFactory 의 차이점을 이해하지 못 했거나 인터뷰 에서 Spring의 BeanFactory와 FactoryBean의 차이점 에 대해 질문을받을 수 있습니다 . . 우리 중 많은 사람들이 FactoryBean 확장하고 사용 하도록 사용자 정의하지 않았을 것입니다 . 그러나 어떤 프레임 워크가 적용되었는지 검토 할 수 있습니까? 예 : Feign의 FeignClientFactoryBean, mybatis-spring의 MapperFactoryBean, SqlSessionFactoryBean  등은 모두 Spring의 FactoryBean 인터페이스를 구현하고 Bean의 생성 프로세스를 사용자 정의하고 동적 프록시를 통해 Feign 인터페이스 및 Mapper 인터페이스에 대한 프록시 객체를 생성하도록 확장되어 하단의 많은 복잡성을 보호합니다. Http 연결 및 SQL 스 플라이 싱과 같은 반복적 인 비즈니스 로직의 경우 .NET을 개발할 때 구현 클래스를 작성할 필요가 없습니다 .

일반적으로 Spring은 리플렉션 메커니즘을 통해 Bean을 인스턴스화하기 위해 구현 클래스를 지정하기 위해 class 속성을 사용합니다 . 어떤 경우에는 Bean 인스턴스화 프로세스가 더 복잡합니다. 전통적인 방법을 따르면 여기에 많은 구성 정보 를 제공해야합니다 . 구성 방법의 유연성은 제한적이며 이때 코딩 방법 을 사용하여 간단한 방식을 얻을 수있다. Spring은 제공 의 팩토리 인터페이스 org.springframework.bean.factory. 의 FactoryBean 에 대한 이러한 목적을 하고, 사용자는이 인터페이스를 구현하여 Bean을 인스턴스화의 논리를 사용자 정의 할 수 있습니다 .

  • FactoryBean 은 특정 유형의 Bean 인스턴스를 생성 할 수있는 Factory Bean으로 가장 큰 기능 중 하나 는 Bean 생성 프로세스를 사용자 정의 할 수 있도록하는 것 입니다.
  • BeanFactory 는 Spring 컨테이너에서 기본적이고 중요한 클래스로 BeanFactory는 Spring 컨테이너에서 Bean을 생성 및 관리 할 수 ​​있으며 Bean 생성을위한 통합 프로세스를 가지고있다 .

FactoryBean 인터페이스는 다음과 같이 정의됩니다.

public interface FactoryBean<T> {

	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    // 这个方法,我们可以自定义返回bean实例
	@Nullable
	T getObject() throws Exception;

    // 返回bean类型,可判断传入的class类型是否一致
	@Nullable
	Class<?> getObjectType();

    // 默认实现:true-单例,flase-原型
	default boolean isSingleton() {
		return true;
	}

}

주제에 들어가기 전에 약간의 디저트를 먹고 간단한 테스트 예제를 작성한 다음 FactoryBean의 소스 코드로 천천히 들어가서 Bean의 생성 프로세스를 사용자 정의하는 방법을 분석합니다. 공간이 약간 길기 때문에이 기사에서는 먼저 분석에 중점을 둡니다. Class <?> getObjectType () 메서드를 사용하는 경우 다음 기사에서는 getObject ()를 자세히 분석합니다.

주문 관련 서비스 인터페이스 정의

public interface IOrderService {

    void saveOrder();

}

서비스 구현 클래스, @Service라는 스프링 빈 어노테이션이 없으며 사용자 정의 FactoryBean을 통해 Bean을 얻는 방법을 테스트하기 위해 xml에서 Bean을 구성 할 필요가 없습니다.

//@Service
public class OrderServiceImpl implements IOrderService {

    @Override
    public void saveOrder() {
        System.out.println("-----创建订单------");
    }
}

Custom FactoryBean 구현 : OrderFactoryBean, @Component 주석을 추가하는 것을 잊지 마십시오.이 빈은 스프링 ioc 컨테이너 (orderFactoryBean)에 의해 관리됩니다.

/**
 * @description: 自定义FactoryBean实现
 * @author: stwen_gan
 * @date: 
 **/
@Component
public class OrderFactoryBean implements FactoryBean {

    /**
     * 自定义bean的创建过程
     */
    @Override
    public Object getObject() throws Exception {
        System.out.println("-----调用OrderFactoryBean.getObject----");
        // 1、直接new
        IOrderService orderService = new OrderServiceImpl();
        return orderService;

        // 2、通过动态代理,无需实现类,如 Mybatis的xxxMapper接口
//        OrderMapper bean = (OrderMapper) Proxy.newProxyInstance(OrderFactoryBean.class.getClassLoader(), new Class[]{OrderMapper.class}, new InvocationHandler() {
//            @Override
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                // todo
//                System.out.println(method.getName());
//                return null;
//            }
//        });
//        return bean;

    }

    /**
     * 返回bean的class类型
     */
    @Override
    public Class<?> getObjectType() {
        return IOrderService.class;

    }

    /**
     * 是否单例,默认单例
     * @return
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

편의상 getObject () 메소드에서 직접 OrderServiceImpl 구현 클래스를 새로 만들 수 있습니다 . 물론 동적 프록시를 통해 프록시 객체를 생성하는 것도 가능합니다. 여기에서는 분석되지 않고 주석 처리되었으며주의없이 직접 테스트 할 수 있습니다.

테스트 카테고리 :

/**
 * @description: 测试
 * @author: stwen_gan
 * @date: 
 **/
public class FactoryBeanTest {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(MyConfig.class);

        //测试自定义FactoryBean实现getObject产生bean 
        IOrderService bean = context.getBean(IOrderService.class);
        System.out.println(bean);
        System.out.println("---------------------");

        System.out.println(context.getBean("orderFactoryBean"));// bean是OrderServiceImpl,并不是OrderFactoryBean
        System.out.println(context.getBean("orderFactoryBean"));// 测试是否单例
        System.out.println(context.getBean("orderFactoryBean"));// 测试是否单例
    }
}

출력 실행 :

위의 isSingleton 메소드가 true (singleton)를 리턴하기 때문에 획득 한 Bean 인스턴스가 모두 동일하다는 것을 알 수 있습니다.

질문 :

  1. 이 IOrderService 인터페이스와 OrderServiceImpl 구현 클래스는 빈 주석 (일반 인터페이스 / 클래스)을 추가하지 않았지만 context.getBean 메소드를 통해 IoC 컨테이너에서 가져올 수 있습니다.
  2. context.getBean ( "orderFactoryBean")에 의해 획득 된 빈 객체는 OrderFactoryBean 객체 자체가 아니라 OrderFactoryBean.getObject 메소드에서 반환 된 OrderServiceImpl 객체입니다. 어떻게 구현됩니까?
  3. OrderFactoryBean 객체 자체를 얻으려면 어떻게해야합니까?

Spring FactoryBean의 미스테리를 이해하기 위해 AbstractApplicationContext의 메소드 인 getBean 메소드로 직접 시작합니다  . 많은 서브 클래스가 다음과 같이 메소드를 오버로드합니다.

	// 根据Class类型获取bean
    @Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		// 检查BeanFactory的激活状态
        assertBeanFactoryActive();
        //getBeanFactory()获取到的是一个DefaultListableBeanFactory的默认实例
		return getBeanFactory().getBean(requiredType);
	}

    // 根据beanName获取bean
	@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name);
	}

여기서는 Class 타입에 따라 Bean을 얻는 getBean (Class <T> requiredType) 메소드 만을 분석하고 전달한 것은 IOrderService.class 타입입니다.

그중 getBeanFactory ()는 DefaultListableBeanFactory 의 기본 인스턴스를 가져 오므로 , getBean 메소드의 특정 구현을 보려면 DefaultListableBeanFactory로 이동해야합니다.

DefaultListableBeanFactory # getBean (Class <T> requiredType)

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}

	@Override
	public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
		Assert.notNull(requiredType, "Required type must not be null");
        // 根据传入的Class类型、参数等解析bean
		Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
		if (resolved == null) {
			throw new NoSuchBeanDefinitionException(requiredType);
		}
		return (T) resolved;
	}

위의 코드에서 우리는 resolveBean 메소드에 초점을 맞 춥니 다.

	@Nullable
	private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
        // 解析bean
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
        //如果当前Spring容器获取不到相应的bean信息,则从父容器中获取
        //SpringMVC是一个很典型的父子容器
		BeanFactory parent = getParentBeanFactory();
		if (parent instanceof DefaultListableBeanFactory) {
			return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
		}
		else if (parent != null) {
			ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
			if (args != null) {
				return parentProvider.getObject(args);
			}
			else {
				return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
			}
		}
		return null;
	}

resolveNamedBean 메소드, beanName 해결 방법에 중점을 둡니다.

	@Nullable
	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
        //这个方法是根据传入的Class类型来获取BeanName,因为一个接口可以有多个实现类的情况(多态),
        //所以这里返回的是一个String数组,这个过程也比较复杂。
        //这里需要注意的是,我们调用getBean方法传入的type为com.example.demo.spring.factorybean.IOrderService类型,但是我们没有在Spring容器中注入IOrderService类型的Bean
        //正常来说我们在这里是获取不到beanName的,但是事实是不是这样呢?看下面我们对getBeanNamesForType的分析
		String[] candidateNames = getBeanNamesForType(requiredType);

        // 如果有多个BeanName,则筛选合适的BeanName
        // 自动注入相关的判断
		if (candidateNames.length > 1) {
            // 自动注入的bean候选者
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
                // list 转 String 数组,放入候选的beanNames中
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}

        //如果BeanName只有一个, 我们调用getBean方法来获取Bean实例来放入到NamedBeanHolder中
        //这里getBean是根据beanName,bean的Class类型和参数来获取bean
		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
		}
		else if (candidateNames.length > 1) {
            // 将候选bean放入一个map
			Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
			for (String beanName : candidateNames) {
                //从单例池中根据beanName获取该bean对象
				if (containsSingleton(beanName) && args == null) {
                    // 根据beanName获取bean
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
                    //单例池中没有获取到该bean,则通过getType方法继续获取Bean实例
					candidates.put(beanName, getType(beanName));
				}
			}
            //有多个Bean实例的话 则取带有Primary注解或者带有Primary信息的Bean
			String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
			if (candidateName == null) {
                //如果没有Primary注解或者Primary相关的信息,则取优先级高的Bean实例
				candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
			}
            // 最终获取到一个合适的beanName后,就可以根据Class类型,继续调用getBean方法获取Bean实例
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null || beanInstance instanceof Class) {
					beanInstance = getBean(candidateName, requiredType.toClass(), args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
            // 如果都没有获取到,则抛异常
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}

		return null;
	}

위의 메소드에서 전달한 유형은 com.example.demo.spring.factorybean.IOrderService 인터페이스 유형이지만이 인터페이스 또는 구현 클래스의 Bean을 Spring 컨테이너에 구성하지 않았으므로 getBeanNamesForType에서 가져 오는 방법 beanName은 어떻습니까?
아래에서 getBeanNamesForType을 분석합니다.

	@Override
	public String[] getBeanNamesForType(ResolvableType type) {
		return getBeanNamesForType(type, true, true);
	}

	@Override
	public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		Class<?> resolved = type.resolve();
        // type解析不为空
		if (resolved != null && !type.hasGenerics()) {
			return getBeanNamesForType(resolved, includeNonSingletons, allowEagerInit);
		}
		else {
			return doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		}
	}

	@Override
	public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
		if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
			return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
		}
        //先从缓存中获取:根据Class类型获取符合的beanNames
		Map<Class<?>, String[]> cache =
				(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
		String[] resolvedBeanNames = cache.get(type);
        // 获取到直接返回
		if (resolvedBeanNames != null) {
			return resolvedBeanNames;
		}
        // 获取不到,则调用doGetBeanNamesForType方法获取符合的beanNames
        // 下面会详细分析此方法
		resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
        //判断我们传入的类能不能被当前类加载加载
		if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
            //放入到缓存中,方便下次直接从缓存中获取
            //key:IOrderService,Value:orderFactoryBean
			cache.put(type, resolvedBeanNames);
		}
		return resolvedBeanNames;
	}

발견 된 디버깅 및 분석, 캐시 캐시, 핵심은 Class의 com.example.demo.spring.factorybean.IOrderService를 전달 했지만 사용자 정의 값 FactoryBean 구현 OrderFactoryBean 해당 beanName --orderFactoryBean (우리는 @Component 주석이 OrderFactoryBean 클래스에 추가되고 Spring IoC 관리에 추가됨)이 beanName은 orderService 가 아닙니다 . 이것도이 기사의 초점이며,이 문제를 이해하는 것이 매우 중요합니다 OrderFactoryBean에 해당하는 beanName을 IOrderService.class와 어떻게 연관 시키는가?

그러므로 우리는 doGetBeanNamesForType 메소드를 분석 할 필요가 있습니다. 들어오는 IOrderService.Class 유형을 통해 OrderFactoryBean 의 beanName을 얻는 방법 :

	private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		List<String> result = new ArrayList<>();

		// Check all bean definitions.
        //循环检查IoC中所有的beanName,这个是在Spring容器启动解析Bean的时候放入到这个List中的
		for (String beanName : this.beanDefinitionNames) {
			// Only consider bean as eligible if the bean name
			// is not defined as alias for some other bean.
            // 只有当bean名称没有定义为其他bean的别名时,才是符合要求的
			if (!isAlias(beanName)) {
				try {
                    //根据beanName获取RootBeanDefinition
					RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
					// Only check bean definition if it is complete.
                    // 这里检查beanDefinition信息的完整性
					if (!mbd.isAbstract() && (allowEagerInit ||
							(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
									!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                        // 根据beanName与RootBeanDefinition 判断是否FactoryBean的子类
						boolean isFactoryBean = isFactoryBean(beanName, mbd);
						BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();

                        // 类型、beanName等信息是否匹配
						boolean matchFound = false;
						boolean allowFactoryBeanInit = allowEagerInit || containsSingleton(beanName);
						boolean isNonLazyDecorated = dbd != null && !mbd.isLazyInit();
						// 普通bean(非FactoryBean子类)
                        if (!isFactoryBean) {
							if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
								matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
							}
						}
                        // FactoryBean 子类
						else  {
							if (includeNonSingletons || isNonLazyDecorated ||
									(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
                                // 下面会重点分析此isTypeMatch方法
								matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
							}
                            // matchFound=false时
							if (!matchFound) {
								// In case of FactoryBean, try to match FactoryBean instance itself next.
                                //如果不匹配,需要给beanName添加一个统一的前缀&,&beanName 表示这是FactoryBean子类对应的beanName
								beanName = FACTORY_BEAN_PREFIX + beanName;
								matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
							}
						}
                        // matchFound=true,则表示符合,添加此beanName到result返回
						if (matchFound) {
							result.add(beanName);
						}
					}
				}

			}
		}
        // 省略部分无关代码。。。。

		return StringUtils.toStringArray(result);
	}

위의 메소드에서 먼저 Spring의 모든 beanName을 반복하고 beanName에 따라 해당 RootBeanDefinition을 얻은 다음 전달한 ResolvableType 유형 (예 : IOrderService.class  ) 에 따라 현재 beanName과 일치하는지 여부 판단합니다. matchFound = isTypeMatch ( beanName, 유형, allowFactoryBeanInit) .

OrderFactoryBean에 해당하는 beanName 을 탐색 하고 그것이 FactoryBean의 서브 클래스임을 발견 하면 else에 들어가고 isTypeMatch 메소드를 사용하여 우리가 전달한 IOrderService.class 와 일치 하는지 여부를 결정합니다 . 다음과 같이 디버깅은 일치하는 것을 찾습니다. 즉, matchFound = true이고 마지막으로이 beanName이 결과 반환에 추가됩니다.

그중 beanName = FACTORY_BEAN_PREFIX + beanName; (FACTORY_BEAN_PREFIX = "&") , 여기서 matchFound = false 일 때 왜 FactoryBean 하위 클래스에 해당하는 beanName에 접두사 &를 추가합니까?

-> FactoryBean 하위 클래스 객체 빈 자체를 얻기 위해  context.getBean ( " & orderFactoryBean")을 전달 하고 직접 테스트 한 다음 출력 할 수 있습니다.

com.example.demo.spring.factorybean.OrderFactoryBean@1f0f1111

다음은 조건부 중단 점을 추가하는 디버깅을위한 작은 트릭입니다.

그래서 여기서 우리는 판단 유형을 일치시키는 방법 인 isTypeMatch 메소드 를 분석 할 것 입니다. OrderFactoryBeanbeanNameIOrderService에 어떻게 대응 할까요?

	protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)
			throws NoSuchBeanDefinitionException {

        //转换beanName,这里只探讨beanName为orderFactoryBean时isTypeMatch返回的结果
		String beanName = transformedBeanName(name);
		boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name);

        //这里是用AbstractApplicationContext的子类来从Spring容器中获取Bean,
        //获取beanName为orderFactoryBean的Bean实例 (IoC是可以获取到的,因为我们有在OrderFactoryBean类上添加@Component注解)
		Object beanInstance = getSingleton(beanName, false);// beanName:orderFactoryBean-->OrderFactoryBean
		if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
            //判断获取到的OrderFactoryBean是否是FactoryBean的实例
			if (beanInstance instanceof FactoryBean) {
                //这里判断beanName是不是以&开头,这里明显不是(“orderFactoryBean”),这里可以想一下什么情况下会有&开头的Bean,上面也有说明
				if (!isFactoryDereference) {
                    //这里就是从OrderFactoryBean实例中获取type类型,下面会分析一下这个方法
					Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
                    //从OrderFactoryBean中获取到的type类型和我们传入的类型是不是同一种类型,是则直接返回true
					return (type != null && typeToMatch.isAssignableFrom(type));
				}
				else {
					return typeToMatch.isInstance(beanInstance);
				}
			}
        // 省略。。。

그중 Object beanInstance = getSingleton (beanName, false) , Spring 컨테이너에서 해당 Bean을 가져 오려면 다음과 같은 질문이 있습니다.

Spring 컨테이너에서 Bean을 얻기 위해 AbstractApplicationContext의 서브 클래스를 사용하는 것과 컨테이너에서 Bean을 얻기 위해 BeanFactory의 서브 클래스를 사용하는 것의 차이점은 무엇입니까?

전자는 beanName (orderFactoryBean : OrderFactoryBean)에 해당하는 Bean 인스턴스 자체를 얻고 후자는 BeanFactory 하위 클래스 (예 : orderFactoryBean : OrderServiceImpl)의 사용자 정의 getObject () 메소드에 의해 반환 된 인스턴스 객체를 얻습니다.

아래에서 getTypeForFactoryBean 을 분석 하십시오.

	@Nullable
	protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
		try {
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged((PrivilegedAction<Class<?>>)
						factoryBean::getObjectType, getAccessControlContext());
			}
			else {
                //看到这是不是很熟悉了,实际调用FactoryBean实例的getObjectType()方法
				return factoryBean.getObjectType();
			}
		}
        // 省略。。。
	}

위 분석의 계층을 통해 마침내 호출 getObjectType 메소드 의 사용자 정의 OrderFactoryBean발견 하여 값을 얻었습니다 : com.example.demo.spring.factorybean.IOrderService , 우리는 유형이 동일한 유형을 전달합니다. 분석에 따르면 여기에서 true를 반환합니다 . isTypeMatch가 true를 반환하면 반환하는 beanName은 orderFactoryBean 입니다. 그래서, 우리는 마침내 이해 : 우리가 context.getBean (전화 IOrderService 의 .class)를 둔다는 OrderFactoryBean 해당 beanName에IOrderService이 를 연결합니다.

요약하자면

IOrderService / OrderServiceImpl 을 Spring Bean으로 구성 하지 않았습니다 . 즉 Spring 컨테이너에 해당 BeanDefinition이없고 IOrderService.class통해 해당 Bean을 얻을 수 없지만 Factory Bean (OrderFactoryBean)을 사용자 정의했습니다. IOrderService 의 유형은 다음과 같이 관련됩니다.

IOrderService bean = context.getBean (IOrderService.class)를 통해 유형에 따라 bean 얻을 때   , 기본 Spring은 먼저 해당 beanName을 얻습니다.

먼저 Spring 컨테이너의 모든 beanNames를 반복 한 다음 beanName에 따라 해당 BeanDefinition을 가져옵니다. 현재 Bean이 FactoryBean 유형이면 BeanName에 따라 Spring 컨테이너에서 해당 Bean 인스턴스를 가져온 다음 얻은 Bean 인스턴스의 getObjectType 메서드 를 호출하여 가져옵니다. 클래스 유형으로 이동하여이 클래스 유형과 전달한 클래스가 동일한 유형인지 확인합니다. 그렇다면이 beanName을 반환합니다. 이것은 우리 예제에 해당합니다. orderFactoryBean에 따라 OrderFactoryBean 인스턴스를 가져오고 OrderFactoryBean의 getObjectType 메소드를 호출하여 반환 값 IOrderService.class 를 가져 옵니다 . 우리가 전달한 유형과 일치 하므로 여기에서 얻은 beanName은 orderFactoryBean 입니다. 환언 여기에서는 beanName에이 orderFactoryBean 매핑 IOrderService 유형 : 순서 , IOrderService beanName에 orderFactoryBean의 종류에 대응 . 이 기사를 통해 Factory의 세 가지 메소드에서 getObjectType의 역할을 이해하고 다음 기사에서 분석 할 것입니다 : getBean (String name, Class requiredType, Object ... args) 이 메소드는 FactoryBean이 최종적으로 사용자 정의 Bean을 리턴하는 방법입니다.

마지막으로 우리가 전달한 클래스 유형 (IOrderService.calss)과 사용자 정의 FactoryBean 하위 클래스가 어떻게 관련되는지 설명하는 FactoryBean 흐름도의 간단한 버전을 그렸습니다. 즉, getBean (IOrderService.class)를 호출합니다. , 맨 아래 계층은 결국 factoryBean.getObjectType ()호출 하여 전체 컨텍스트를 명확히하는 데 도움이됩니다 (그림을 확대하려면 클릭).

참조 : https://blog.csdn.net/zknxx/article/details/79572387

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

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

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

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

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

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

깊고 충만한 공개 계정 0.0

 

추천

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