溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring cloud中FeignClientBuilder的用法

發(fā)布時間:2021-07-01 11:57:31 來源:億速云 閱讀:1176 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要講解了“spring cloud中FeignClientBuilder的用法”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“spring cloud中FeignClientBuilder的用法”吧!

本文主要研究一下spring cloud的FeignClientBuilder

FeignClientBuilder

spring-cloud-openfeign-core-2.2.0.M1-sources.jar!/org/springframework/cloud/openfeign/FeignClientBuilder.java

public class FeignClientBuilder {

	private final ApplicationContext applicationContext;

	public FeignClientBuilder(final ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}

	public <T> Builder<T> forType(final Class<T> type, final String name) {
		return new Builder<>(this.applicationContext, type, name);
	}

	/**
	 * Builder of feign targets.
	 *
	 * @param <T> type of target
	 */
	public static final class Builder<T> {

		private FeignClientFactoryBean feignClientFactoryBean;

		private Builder(final ApplicationContext applicationContext, final Class<T> type,
				final String name) {
			this.feignClientFactoryBean = new FeignClientFactoryBean();

			this.feignClientFactoryBean.setApplicationContext(applicationContext);
			this.feignClientFactoryBean.setType(type);
			this.feignClientFactoryBean.setName(FeignClientsRegistrar.getName(name));
			this.feignClientFactoryBean.setContextId(FeignClientsRegistrar.getName(name));
			// preset default values - these values resemble the default values on the
			// FeignClient annotation
			this.url("").path("").decode404(false).fallback(void.class)
					.fallbackFactory(void.class);
		}

		public Builder url(final String url) {
			this.feignClientFactoryBean.setUrl(FeignClientsRegistrar.getUrl(url));
			return this;
		}

		public Builder contextId(final String contextId) {
			this.feignClientFactoryBean.setContextId(contextId);
			return this;
		}

		public Builder path(final String path) {
			this.feignClientFactoryBean.setPath(FeignClientsRegistrar.getPath(path));
			return this;
		}

		public Builder decode404(final boolean decode404) {
			this.feignClientFactoryBean.setDecode404(decode404);
			return this;
		}

		public Builder fallback(final Class<T> fallback) {
			FeignClientsRegistrar.validateFallback(fallback);
			this.feignClientFactoryBean.setFallback(fallback);
			return this;
		}

		public Builder fallbackFactory(final Class<T> fallbackFactory) {
			FeignClientsRegistrar.validateFallbackFactory(fallbackFactory);
			this.feignClientFactoryBean.setFallbackFactory(fallbackFactory);
			return this;
		}

		/**
		 * @param <T> the target type of the Feign client to be created
		 * @return the created Feign client
		 */
		public <T> T build() {
			return this.feignClientFactoryBean.getTarget();
		}

	}

}
  • FeignClientBuilder提供了forType靜態(tài)方法用于創(chuàng)建Builder;Builder的構(gòu)造器創(chuàng)建了FeignClientFactoryBean,其build方法使用FeignClientFactoryBean的getTarget()來創(chuàng)建目標feign client

實例

public class FeignClientBuilderTests {

	@Rule
	public ExpectedException thrown = ExpectedException.none();

	private FeignClientBuilder feignClientBuilder;

	private ApplicationContext applicationContext;

	private static Object getDefaultValueFromFeignClientAnnotation(
			final String methodName) {
		final Method method = ReflectionUtils.findMethod(FeignClient.class, methodName);
		return method.getDefaultValue();
	}

	private static void assertFactoryBeanField(final FeignClientBuilder.Builder builder,
			final String fieldName, final Object expectedValue) {
		final Field factoryBeanField = ReflectionUtils
				.findField(FeignClientBuilder.Builder.class, "feignClientFactoryBean");
		ReflectionUtils.makeAccessible(factoryBeanField);
		final FeignClientFactoryBean factoryBean = (FeignClientFactoryBean) ReflectionUtils
				.getField(factoryBeanField, builder);

		final Field field = ReflectionUtils.findField(FeignClientFactoryBean.class,
				fieldName);
		ReflectionUtils.makeAccessible(field);
		final Object value = ReflectionUtils.getField(field, factoryBean);
		assertThat(value).as("Expected value for the field '" + fieldName + "':")
				.isEqualTo(expectedValue);
	}

	@Before
	public void setUp() {
		this.applicationContext = Mockito.mock(ApplicationContext.class);
		this.feignClientBuilder = new FeignClientBuilder(this.applicationContext);
	}

	@Test
	public void safetyCheckForNewFieldsOnTheFeignClientAnnotation() {
		final List<String> methodNames = new ArrayList();
		for (final Method method : FeignClient.class.getMethods()) {
			methodNames.add(method.getName());
		}
		methodNames.removeAll(
				Arrays.asList("annotationType", "value", "serviceId", "qualifier",
						"configuration", "primary", "equals", "hashCode", "toString"));
		Collections.sort(methodNames);
		// If this safety check fails the Builder has to be updated.
		// (1) Either a field was removed from the FeignClient annotation and so it has to
		// be removed
		// on this builder class.
		// (2) Or a new field was added and the builder class has to be extended with this
		// new field.
		assertThat(methodNames).containsExactly("contextId", "decode404", "fallback",
				"fallbackFactory", "name", "path", "url");
	}

	@Test
	public void forType_preinitializedBuilder() {
		// when:
		final FeignClientBuilder.Builder builder = this.feignClientBuilder
				.forType(FeignClientBuilderTests.class, "TestClient");

		// then:
		assertFactoryBeanField(builder, "applicationContext", this.applicationContext);
		assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
		assertFactoryBeanField(builder, "name", "TestClient");
		assertFactoryBeanField(builder, "contextId", "TestClient");

		// and:
		assertFactoryBeanField(builder, "url",
				getDefaultValueFromFeignClientAnnotation("url"));
		assertFactoryBeanField(builder, "path",
				getDefaultValueFromFeignClientAnnotation("path"));
		assertFactoryBeanField(builder, "decode404",
				getDefaultValueFromFeignClientAnnotation("decode404"));
		assertFactoryBeanField(builder, "fallback",
				getDefaultValueFromFeignClientAnnotation("fallback"));
		assertFactoryBeanField(builder, "fallbackFactory",
				getDefaultValueFromFeignClientAnnotation("fallbackFactory"));
	}

	@Test
	public void forType_allFieldsSetOnBuilder() {
		// when:
		final FeignClientBuilder.Builder builder = this.feignClientBuilder
				.forType(FeignClientBuilderTests.class, "TestClient").decode404(true)
				.fallback(Object.class).fallbackFactory(Object.class).path("Path/")
				.url("Url/");

		// then:
		assertFactoryBeanField(builder, "applicationContext", this.applicationContext);
		assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
		assertFactoryBeanField(builder, "name", "TestClient");

		// and:
		assertFactoryBeanField(builder, "url", "http://Url/");
		assertFactoryBeanField(builder, "path", "/Path");
		assertFactoryBeanField(builder, "decode404", true);
		assertFactoryBeanField(builder, "fallback", Object.class);
		assertFactoryBeanField(builder, "fallbackFactory", Object.class);
	}

	@Test
	public void forType_build() {
		// given:
		Mockito.when(this.applicationContext.getBean(FeignContext.class))
				.thenThrow(new ClosedFileSystemException()); // throw an unusual exception
																// in the
																// FeignClientFactoryBean
		final FeignClientBuilder.Builder builder = this.feignClientBuilder
				.forType(TestClient.class, "TestClient");

		// expect: 'the build will fail right after calling build() with the mocked
		// unusual exception'
		this.thrown.expect(Matchers.isA(ClosedFileSystemException.class));
		builder.build();
	}

}
  • FeignClientBuilderTests驗證了safetyCheckForNewFieldsOnTheFeignClientAnnotation、forType_preinitializedBuilder、forType_allFieldsSetOnBuilder、forType_build

小結(jié)

FeignClientBuilder提供了forType靜態(tài)方法用于創(chuàng)建Builder;Builder的構(gòu)造器創(chuàng)建了FeignClientFactoryBean,其build方法使用FeignClientFactoryBean的getTarget()來創(chuàng)建目標feign client

感謝各位的閱讀,以上就是“spring cloud中FeignClientBuilder的用法”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對spring cloud中FeignClientBuilder的用法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI