Skip to content

Commit f79084f

Browse files
committed
Refactor Feign spec customization and autoconfig
Introduce a pluggable customization model for FeignClientSpecification and reorganize related auto-configuration. Add FeignClientSpecificationCustomizer and AutoRefreshCapabilityCustomizer (injects AutoRefreshCapability into default specs). Move FeignClientSpecificationPostProcessor into beans.factory.config and make it BeanFactoryAware to apply all available customizers; delete the old processor. Add FeignAutoConfiguration to register a NoOpRequestInterceptor via FeignBuilderCustomizer and to expose the post-processor bean. Update EnableFeignAutoRefresh to import the new customizer, adjust FeignClientAutoRefreshAutoConfiguration to use the new packages and remove duplicated beans, update AutoConfiguration.imports, and rename/move/update tests to match the refactor.
1 parent 8817574 commit f79084f

16 files changed

Lines changed: 232 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package io.microsphere.spring.cloud.openfeign;
19+
20+
import org.springframework.cloud.openfeign.FeignClientSpecification;
21+
22+
import java.util.function.BiConsumer;
23+
24+
/**
25+
* The Customizer of {@link FeignClientSpecification}
26+
*
27+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
28+
* @see FeignClientSpecification
29+
* @since 1.0.0
30+
*/
31+
public interface FeignClientSpecificationCustomizer extends BiConsumer<FeignClientSpecification, String> {
32+
33+
/**
34+
* Customizes {@link FeignClientSpecification} bean and bean name
35+
*
36+
* @param specification {@link FeignClientSpecification}
37+
* @param beanName the bean name of {@link FeignClientSpecification}
38+
*/
39+
void customize(FeignClientSpecification specification, String beanName);
40+
41+
@Override
42+
default void accept(FeignClientSpecification specification, String beanName) {
43+
customize(specification, beanName);
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package io.microsphere.spring.cloud.openfeign.autoconfigure;
2+
3+
import feign.Feign;
4+
import io.microsphere.spring.cloud.openfeign.beans.factory.config.FeignClientSpecificationPostProcessor;
5+
import io.microsphere.spring.cloud.openfeign.components.NoOpRequestInterceptor;
6+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
7+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
8+
import org.springframework.cloud.openfeign.FeignBuilderCustomizer;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.context.annotation.Configuration;
11+
12+
import static io.microsphere.spring.cloud.openfeign.components.NoOpRequestInterceptor.INSTANCE;
13+
14+
/**
15+
* The Auto-Configuration class for Spring Cloud OpenFeign
16+
*
17+
* @author <a href="mailto:maimengzzz@gmail.com">韩超</a>
18+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
19+
* @since 0.0.1
20+
*/
21+
@Configuration(proxyBeanMethods = false)
22+
@ConditionalOnClass(Feign.class)
23+
@AutoConfigureAfter(name = "org.springframework.cloud.openfeign.FeignAutoConfiguration")
24+
public class FeignAutoConfiguration {
25+
26+
/**
27+
* Creates a {@link FeignBuilderCustomizer} that adds the {@link NoOpRequestInterceptor}
28+
* as a default request interceptor to every Feign client builder.
29+
*
30+
* <p>Example Usage:
31+
* <pre>{@code
32+
* // Automatically registered as a Spring bean; customizes every Feign builder
33+
* FeignBuilderCustomizer customizer = addDefaultRequestInterceptorCustomizer();
34+
* }</pre>
35+
*
36+
* @return a {@link FeignBuilderCustomizer} that adds the {@link NoOpRequestInterceptor}
37+
*/
38+
@Bean
39+
public FeignBuilderCustomizer addDefaultRequestInterceptorCustomizer() {
40+
return builder -> {
41+
builder.requestInterceptor(INSTANCE);
42+
};
43+
}
44+
45+
/**
46+
* Creates the {@link FeignClientSpecificationPostProcessor} bean that injects
47+
* the {@link io.microsphere.spring.cloud.openfeign.autorefresh.AutoRefreshCapability}
48+
* into default Feign client specifications.
49+
*
50+
* <p>Example Usage:
51+
* <pre>{@code
52+
* // Automatically registered as a Spring bean
53+
* FeignClientSpecificationPostProcessor processor = feignClientSpecificationPostProcessor();
54+
* }</pre>
55+
*
56+
* @return a new {@link FeignClientSpecificationPostProcessor} instance
57+
*/
58+
@Bean
59+
public FeignClientSpecificationPostProcessor feignClientSpecificationPostProcessor() {
60+
return new FeignClientSpecificationPostProcessor();
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package io.microsphere.spring.cloud.openfeign.autoconfigure;
22

3-
import io.microsphere.spring.cloud.openfeign.autoconfigure.EnableFeignAutoRefresh.Marker;
3+
import io.microsphere.spring.cloud.openfeign.autorefresh.EnableFeignAutoRefresh;
4+
import io.microsphere.spring.cloud.openfeign.autorefresh.EnableFeignAutoRefresh.Marker;
45
import io.microsphere.spring.cloud.openfeign.autorefresh.FeignClientConfigurationChangedListener;
56
import io.microsphere.spring.cloud.openfeign.autorefresh.FeignComponentRegistry;
6-
import io.microsphere.spring.cloud.openfeign.components.NoOpRequestInterceptor;
77
import org.springframework.beans.factory.BeanFactory;
88
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
99
import org.springframework.boot.context.event.ApplicationReadyEvent;
10-
import org.springframework.cloud.openfeign.FeignBuilderCustomizer;
1110
import org.springframework.cloud.openfeign.FeignClientProperties;
1211
import org.springframework.context.ConfigurableApplicationContext;
1312
import org.springframework.context.annotation.Bean;
1413
import org.springframework.context.event.EventListener;
1514

16-
import static io.microsphere.spring.cloud.openfeign.components.NoOpRequestInterceptor.INSTANCE;
17-
1815
/**
1916
* The Auto-Configuration class for {@link EnableFeignAutoRefresh}
2017
*
@@ -26,25 +23,6 @@
2623
@ConditionalOnBean(Marker.class)
2724
public class FeignClientAutoRefreshAutoConfiguration {
2825

29-
/**
30-
* Creates a {@link FeignBuilderCustomizer} that adds the {@link NoOpRequestInterceptor}
31-
* as a default request interceptor to every Feign client builder.
32-
*
33-
* <p>Example Usage:
34-
* <pre>{@code
35-
* // Automatically registered as a Spring bean; customizes every Feign builder
36-
* FeignBuilderCustomizer customizer = addDefaultRequestInterceptorCustomizer();
37-
* }</pre>
38-
*
39-
* @return a {@link FeignBuilderCustomizer} that adds the {@link NoOpRequestInterceptor}
40-
*/
41-
@Bean
42-
public FeignBuilderCustomizer addDefaultRequestInterceptorCustomizer() {
43-
return builder -> {
44-
builder.requestInterceptor(INSTANCE);
45-
};
46-
}
47-
4826
/**
4927
* Handles the {@link ApplicationReadyEvent} to register the
5028
* {@link FeignClientConfigurationChangedListener} after the application is fully initialized.
@@ -84,28 +62,9 @@ public FeignComponentRegistry feignClientRegistry(FeignClientProperties clientPr
8462
return new FeignComponentRegistry(clientProperties.getDefaultConfig(), beanFactory);
8563
}
8664

87-
/**
88-
* Creates the {@link FeignClientSpecificationPostProcessor} bean that injects
89-
* the {@link io.microsphere.spring.cloud.openfeign.autorefresh.AutoRefreshCapability}
90-
* into default Feign client specifications.
91-
*
92-
* <p>Example Usage:
93-
* <pre>{@code
94-
* // Automatically registered as a Spring bean
95-
* FeignClientSpecificationPostProcessor processor = feignClientSpecificationPostProcessor();
96-
* }</pre>
97-
*
98-
* @return a new {@link FeignClientSpecificationPostProcessor} instance
99-
*/
100-
@Bean
101-
public FeignClientSpecificationPostProcessor feignClientSpecificationPostProcessor() {
102-
return new FeignClientSpecificationPostProcessor();
103-
}
104-
10565
private void registerFeignClientConfigurationChangedListener(ApplicationReadyEvent event) {
10666
ConfigurableApplicationContext context = event.getApplicationContext();
10767
FeignComponentRegistry feignComponentRegistry = context.getBean(FeignComponentRegistry.class);
10868
context.addApplicationListener(new FeignClientConfigurationChangedListener(feignComponentRegistry));
10969
}
110-
111-
}
70+
}

microsphere-spring-cloud-openfeign/src/main/java/io/microsphere/spring/cloud/openfeign/autoconfigure/FeignClientSpecificationPostProcessor.java

Lines changed: 0 additions & 55 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package io.microsphere.spring.cloud.openfeign.autorefresh;
19+
20+
import io.microsphere.logging.Logger;
21+
import io.microsphere.spring.cloud.openfeign.FeignClientSpecificationCustomizer;
22+
import org.springframework.cloud.openfeign.FeignClientSpecification;
23+
24+
import static io.microsphere.logging.LoggerFactory.getLogger;
25+
import static io.microsphere.util.ArrayUtils.arrayToString;
26+
import static io.microsphere.util.ArrayUtils.combine;
27+
28+
/**
29+
* The {@link FeignClientSpecificationCustomizer} class to register the bean of {@link AutoRefreshCapability}
30+
*
31+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
32+
* @see AutoRefreshCapability
33+
* @since 1.0.0
34+
*/
35+
class AutoRefreshCapabilityCustomizer implements FeignClientSpecificationCustomizer {
36+
37+
private static final Logger logger = getLogger(AutoRefreshCapabilityCustomizer.class);
38+
39+
/**
40+
* The class of {@link AutoRefreshCapability}
41+
*/
42+
public static final Class<?> AUTO_REFRESH_CAPABILITY_CLASS = AutoRefreshCapability.class;
43+
44+
@Override
45+
public void customize(FeignClientSpecification specification, String beanName) {
46+
if (beanName.startsWith("default.")) {
47+
injectAutoRefreshCapability(specification);
48+
}
49+
}
50+
51+
void injectAutoRefreshCapability(FeignClientSpecification specification) {
52+
Class<?>[] originConfigurationClasses = specification.getConfiguration();
53+
Class<?>[] newConfigurationClasses = combine(AUTO_REFRESH_CAPABILITY_CLASS, originConfigurationClasses);
54+
specification.setConfiguration(newConfigurationClasses);
55+
if (logger.isTraceEnabled()) {
56+
logger.trace("The Configuration classes: before - {} , after - {}", arrayToString(originConfigurationClasses),
57+
arrayToString(newConfigurationClasses));
58+
}
59+
}
60+
}

microsphere-spring-cloud-openfeign/src/main/java/io/microsphere/spring/cloud/openfeign/autoconfigure/EnableFeignAutoRefresh.java renamed to microsphere-spring-cloud-openfeign/src/main/java/io/microsphere/spring/cloud/openfeign/autorefresh/EnableFeignAutoRefresh.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
package io.microsphere.spring.cloud.openfeign.autoconfigure;
1+
package io.microsphere.spring.cloud.openfeign.autorefresh;
22

3+
import io.microsphere.spring.cloud.openfeign.autoconfigure.FeignClientAutoRefreshAutoConfiguration;
34
import org.springframework.context.annotation.Import;
45

56
import java.lang.annotation.Documented;
@@ -22,9 +23,11 @@
2223
@Target(TYPE)
2324
@Documented
2425
@Inherited
25-
@Import(EnableFeignAutoRefresh.Marker.class)
26+
@Import(value = {
27+
EnableFeignAutoRefresh.Marker.class,
28+
AutoRefreshCapabilityCustomizer.class
29+
})
2630
public @interface EnableFeignAutoRefresh {
2731

28-
class Marker {
29-
}
30-
}
32+
class Marker {}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.microsphere.spring.cloud.openfeign.beans.factory.config;
2+
3+
import io.microsphere.spring.beans.factory.config.GenericBeanPostProcessorAdapter;
4+
import io.microsphere.spring.cloud.openfeign.FeignClientSpecificationCustomizer;
5+
import org.springframework.beans.BeansException;
6+
import org.springframework.beans.factory.BeanFactory;
7+
import org.springframework.beans.factory.BeanFactoryAware;
8+
import org.springframework.beans.factory.ObjectProvider;
9+
import org.springframework.beans.factory.config.BeanPostProcessor;
10+
import org.springframework.cloud.openfeign.FeignClientSpecification;
11+
12+
/**
13+
* {@link BeanPostProcessor} for {@link FeignClientSpecification}
14+
*
15+
* @author <a href="mailto:maimengzzz@gmail.com">韩超</a>
16+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
17+
* @see org.springframework.cloud.openfeign.FeignClientSpecification
18+
* @see FeignClientSpecificationCustomizer
19+
* @since 0.0.1
20+
*/
21+
public class FeignClientSpecificationPostProcessor extends GenericBeanPostProcessorAdapter<FeignClientSpecification> implements BeanFactoryAware {
22+
23+
private ObjectProvider<FeignClientSpecificationCustomizer> customizerProvider;
24+
25+
@Override
26+
protected void processAfterInitialization(FeignClientSpecification bean, String beanName) throws BeansException {
27+
customizerProvider.forEach(customizer -> customizer.customize(bean, beanName));
28+
}
29+
30+
@Override
31+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
32+
this.customizerProvider = beanFactory.getBeanProvider(FeignClientSpecificationCustomizer.class);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
io.microsphere.spring.cloud.openfeign.autoconfigure.FeignAutoConfiguration
12
io.microsphere.spring.cloud.openfeign.autoconfigure.FeignClientAutoRefreshAutoConfiguration

0 commit comments

Comments
 (0)