Skip to content

Commit 096c170

Browse files
authored
Merge pull request #25 from mercyblitz/dev-1.x
[Compatiblity] 1.x branch supports the Spring Cloud as low as possible
2 parents af380b7 + 0fbeff5 commit 096c170

File tree

10 files changed

+203
-169
lines changed

10 files changed

+203
-169
lines changed

microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/service/registry/MultipleServiceRegistryTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.alibaba.cloud.nacos.NacosServiceAutoConfiguration;
44
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration;
55
import com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration;
6-
import com.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration;
76
import com.netflix.appinfo.ApplicationInfoManager;
87
import com.netflix.appinfo.InstanceInfo;
98
import io.microsphere.spring.cloud.client.service.registry.autoconfigure.ServiceRegistryAutoConfiguration;
@@ -42,7 +41,6 @@
4241
NacosServiceRegistryAutoConfiguration.class,
4342
NacosServiceAutoConfiguration.class,
4443
NacosDiscoveryAutoConfiguration.class,
45-
UtilIPv6AutoConfiguration.class,
4644
UtilAutoConfiguration.class,
4745
MultipleServiceRegistryTest.class,
4846
ServiceRegistryAutoConfiguration.class,

microsphere-spring-cloud-openfeign/pom.xml

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,22 @@
2626

2727
<dependencies>
2828

29+
<!-- Microsphere Dependencies -->
30+
<dependency>
31+
<groupId>io.github.microsphere-projects</groupId>
32+
<artifactId>microsphere-spring-boot-core</artifactId>
33+
</dependency>
34+
2935
<dependency>
3036
<groupId>org.springframework.cloud</groupId>
3137
<artifactId>spring-cloud-starter-openfeign</artifactId>
3238
<optional>true</optional>
39+
<exclusions>
40+
<exclusion>
41+
<groupId>org.springframework.cloud</groupId>
42+
<artifactId>spring-cloud-netflix-ribbon</artifactId>
43+
</exclusion>
44+
</exclusions>
3345
</dependency>
3446

3547
<dependency>
@@ -44,45 +56,12 @@
4456
<scope>test</scope>
4557
</dependency>
4658

59+
<dependency>
60+
<groupId>org.springframework.cloud</groupId>
61+
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
62+
<optional>true</optional>
63+
</dependency>
4764

4865
</dependencies>
4966

50-
<profiles>
51-
52-
<profile>
53-
<id>spring-cloud-hoxton</id>
54-
<dependencies>
55-
<dependency>
56-
<groupId>org.springframework.cloud</groupId>
57-
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
58-
<optional>true</optional>
59-
</dependency>
60-
</dependencies>
61-
</profile>
62-
63-
<profile>
64-
<id>spring-cloud-2020</id>
65-
<dependencies>
66-
<dependency>
67-
<groupId>org.springframework.cloud</groupId>
68-
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
69-
<optional>true</optional>
70-
</dependency>
71-
</dependencies>
72-
</profile>
73-
74-
<profile>
75-
<id>spring-cloud-2021</id>
76-
<dependencies>
77-
<dependency>
78-
<groupId>org.springframework.cloud</groupId>
79-
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
80-
<optional>true</optional>
81-
</dependency>
82-
</dependencies>
83-
</profile>
84-
85-
</profiles>
86-
87-
8867
</project>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
@Retention(RetentionPolicy.RUNTIME)
1616
@Target({ElementType.TYPE})
1717
@Documented
18-
@Import({FeignClientAutoRefreshConfiguration.class})
18+
@Import(FeignClientAutoRefreshConfiguration.class)
1919
public @interface EnableFeignAutoRefresh {
2020
}
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,61 @@
11
package io.microsphere.spring.cloud.openfeign.autoconfigure;
22

3+
import io.microsphere.logging.Logger;
34
import io.microsphere.spring.cloud.openfeign.autorefresh.AutoRefreshCapability;
45
import org.springframework.beans.BeansException;
56
import org.springframework.beans.factory.config.BeanPostProcessor;
6-
import org.springframework.cloud.openfeign.FeignClientSpecification;
7+
import org.springframework.cloud.context.named.NamedContextFactory;
8+
9+
import java.lang.reflect.Method;
10+
import java.util.Arrays;
11+
12+
import static io.microsphere.logging.LoggerFactory.getLogger;
13+
import static io.microsphere.reflect.MethodUtils.findMethod;
14+
import static io.microsphere.util.ArrayUtils.combine;
15+
import static org.springframework.aop.support.AopUtils.getTargetClass;
16+
import static org.springframework.util.ClassUtils.resolveClassName;
717

818
/**
919
* @author <a href="mailto:[email protected]">韩超</a>
20+
* @author <a href="mailto:[email protected]">Mercy</a>
21+
* @see org.springframework.cloud.openfeign.FeignClientSpecification
1022
* @since 0.0.1
1123
*/
1224
public class FeignClientSpecificationPostProcessor implements BeanPostProcessor {
1325

26+
private static final Logger logger = getLogger(FeignClientSpecificationPostProcessor.class);
27+
28+
private static final Class<?> AUTO_REFRESH_CAPABILITY_CLASS = AutoRefreshCapability.class;
1429

15-
private static final Class<?> AUTO_REFRESH_CAPABILITY = AutoRefreshCapability.class;
30+
private static final String FEIGN_CLIENT_SPECIFICATION_CLASS_NAME = "org.springframework.cloud.openfeign.FeignClientSpecification";
31+
32+
private static final Class<?> FEIGN_CLIENT_SPECIFICATION_CLASS = resolveClassName(FEIGN_CLIENT_SPECIFICATION_CLASS_NAME, null);
33+
34+
private static final Method setConfigurationMethod = findMethod(FEIGN_CLIENT_SPECIFICATION_CLASS, "setConfiguration", Class[].class);
1635

1736
@Override
1837
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
19-
if (bean instanceof FeignClientSpecification && beanName.startsWith("default")) {
20-
injectAutoRefreshCapability((FeignClientSpecification) bean);
38+
Class<?> beanType = getTargetClass(bean);
39+
if (FEIGN_CLIENT_SPECIFICATION_CLASS.isAssignableFrom(beanType) && beanName.startsWith("default")) {
40+
injectAutoRefreshCapability((NamedContextFactory.Specification) bean);
2141
}
2242
return bean;
2343
}
2444

25-
private void injectAutoRefreshCapability(FeignClientSpecification defaultSpecification) {
26-
Class<?>[] originConfigurationClasses = defaultSpecification.getConfiguration();
27-
int length = originConfigurationClasses.length;
28-
Class<?>[] replacedConfigurationClasses = new Class<?>[originConfigurationClasses.length + 1];
29-
//copy origin and inject AutoRefreshCapability
30-
System.arraycopy(originConfigurationClasses, 0, replacedConfigurationClasses, 0, length);
31-
replacedConfigurationClasses[length] = AUTO_REFRESH_CAPABILITY;
32-
defaultSpecification.setConfiguration(replacedConfigurationClasses);
45+
private void injectAutoRefreshCapability(NamedContextFactory.Specification defaultSpecification) {
46+
if (setConfigurationMethod != null) {
47+
Class<?>[] originConfigurationClasses = defaultSpecification.getConfiguration();
48+
Class<?>[] newConfigurationClasses = combine(AUTO_REFRESH_CAPABILITY_CLASS, originConfigurationClasses);
49+
Object arg = newConfigurationClasses;
50+
try {
51+
setConfigurationMethod.setAccessible(true);
52+
setConfigurationMethod.invoke(defaultSpecification, arg);
53+
} catch (Throwable e) {
54+
if (logger.isWarnEnabled()) {
55+
logger.warn("FeignClientSpecification#setConfiguration(Class[]) can't be invoked , instance : {} , args : {}",
56+
defaultSpecification, Arrays.toString(newConfigurationClasses));
57+
}
58+
}
59+
}
3360
}
3461
}

microsphere-spring-cloud-openfeign/src/main/java/io/microsphere/spring/cloud/openfeign/autorefresh/AutoRefreshCapability.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ public Encoder enrich(Encoder encoder) {
9292
return decoratedEncoder;
9393
}
9494

95-
@Override
9695
public ErrorDecoder enrich(ErrorDecoder decoder) {
9796
if (decoder == null)
9897
return null;

microsphere-spring-cloud-openfeign/src/main/java/io/microsphere/spring/cloud/openfeign/components/DecoratedQueryMapEncoder.java

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,54 @@
11
package io.microsphere.spring.cloud.openfeign.components;
22

33
import feign.QueryMapEncoder;
4+
import io.microsphere.logging.Logger;
45
import org.springframework.cloud.openfeign.FeignClientProperties;
56
import org.springframework.cloud.openfeign.FeignContext;
67

8+
import java.lang.invoke.MethodHandle;
79
import java.util.Map;
810

11+
import static io.microsphere.invoke.MethodHandleUtils.findVirtual;
12+
import static io.microsphere.logging.LoggerFactory.getLogger;
13+
914
/**
1015
* @author <a href="mailto:[email protected]">韩超</a>
1116
* @since 0.0.1
1217
*/
1318
public class DecoratedQueryMapEncoder extends DecoratedFeignComponent<QueryMapEncoder> implements QueryMapEncoder {
1419

20+
private static final Logger logger = getLogger(DecoratedQueryMapEncoder.class);
21+
22+
private static final String getQueryMapEncoderMethodName = "getQueryMapEncoder";
23+
24+
private static final MethodHandle getQueryMapEncoderMethodHandle = findVirtual(FeignClientProperties.FeignClientConfiguration.class, getQueryMapEncoderMethodName);
25+
1526
public DecoratedQueryMapEncoder(String contextId, FeignContext feignContext, FeignClientProperties clientProperties, QueryMapEncoder delegate) {
1627
super(contextId, feignContext, clientProperties, delegate);
1728
}
1829

1930
@Override
2031
protected Class<QueryMapEncoder> componentType() {
21-
Class<QueryMapEncoder> queryMapEncoderClass = null;
22-
if (getDefaultConfiguration() != null && getDefaultConfiguration().getQueryMapEncoder() != null)
23-
queryMapEncoderClass = getDefaultConfiguration().getQueryMapEncoder();
24-
25-
if (getCurrentConfiguration() != null && getCurrentConfiguration().getQueryMapEncoder() != null)
26-
queryMapEncoderClass = getCurrentConfiguration().getQueryMapEncoder();
32+
Class<QueryMapEncoder> queryMapEncoderClass = getQueryMapEncoder(getCurrentConfiguration());
33+
if (queryMapEncoderClass == null) {
34+
queryMapEncoderClass = getQueryMapEncoder(getDefaultConfiguration());
35+
}
36+
return queryMapEncoderClass == null ? QueryMapEncoder.class : queryMapEncoderClass;
37+
}
2738

28-
if (queryMapEncoderClass != null)
29-
return queryMapEncoderClass;
30-
return QueryMapEncoder.class;
39+
private Class<QueryMapEncoder> getQueryMapEncoder(FeignClientProperties.FeignClientConfiguration feignClientConfiguration) {
40+
if (feignClientConfiguration == null || getQueryMapEncoderMethodHandle == null) {
41+
return null;
42+
}
43+
Class<QueryMapEncoder> queryMapEncoderClass = null;
44+
try {
45+
queryMapEncoderClass = (Class<QueryMapEncoder>) getQueryMapEncoderMethodHandle.invokeExact(feignClientConfiguration);
46+
} catch (Throwable e) {
47+
if (logger.isWarnEnabled()) {
48+
logger.warn("FeignClientProperties.FeignClientConfiguration#getQueryMapEncoder() method can't be invoked , instance : {}", feignClientConfiguration);
49+
}
50+
}
51+
return queryMapEncoderClass;
3152
}
3253

3354
@Override

microsphere-spring-cloud-openfeign/src/test/java/io/microsphere/spring/cloud/openfeign/BaseTest.java

Lines changed: 12 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,40 @@
11
package io.microsphere.spring.cloud.openfeign;
22

33
import io.microsphere.spring.cloud.openfeign.autoconfigure.EnableFeignAutoRefresh;
4-
import org.junit.jupiter.api.Test;
5-
import org.slf4j.Logger;
6-
import org.slf4j.LoggerFactory;
74
import org.springframework.beans.factory.annotation.Autowired;
85
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
96
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
7+
import org.springframework.boot.test.context.SpringBootTest;
108
import org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration;
11-
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
129
import org.springframework.cloud.endpoint.event.RefreshEvent;
10+
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
1311
import org.springframework.cloud.openfeign.EnableFeignClients;
1412
import org.springframework.context.ApplicationEventPublisher;
1513
import org.springframework.context.annotation.ComponentScan;
16-
import org.springframework.core.env.ConfigurableEnvironment;
17-
import org.springframework.core.env.Environment;
18-
import org.springframework.core.env.MapPropertySource;
19-
import org.springframework.core.env.MutablePropertySources;
2014
import org.springframework.test.context.TestPropertySource;
2115

22-
import java.util.Collections;
23-
import java.util.HashMap;
24-
import java.util.Map;
25-
import java.util.Set;
26-
2716
/**
2817
* @author <a href="mailto:[email protected]">韩超</a>
2918
* @since 0.0.1
3019
*/
31-
@TestPropertySource(properties = {
32-
"spring.main.allow-bean-definition-overriding=true",
33-
"feign.client.config.default.encoder=io.microsphere.spring.cloud.openfeign.encoder.AEncoder",
34-
"feign.client.config.default.request-interceptors[0]=io.microsphere.spring.cloud.openfeign.requestInterceptor.ARequestInterceptor",
35-
"feign.client.config.default.default-request-headers.app=my-app",
36-
"feign.client.config.default.default-query-parameters.sign=my-sign",
37-
})
20+
@SpringBootTest(classes = {BaseTest.class},
21+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
3822
@EnableAutoConfiguration
3923
@ComponentScan(basePackages = "io.microsphere.spring.cloud.openfeign")
24+
@TestPropertySource(
25+
properties = {
26+
"spring.main.allow-bean-definition-overriding=true",
27+
"feign.client.config.default.encoder=io.microsphere.spring.cloud.openfeign.encoder.AEncoder",
28+
"feign.client.config.default.request-interceptors[0]=io.microsphere.spring.cloud.openfeign.requestInterceptor.ARequestInterceptor"
29+
}
30+
)
4031
@EnableFeignClients(clients = BaseClient.class)
4132
@EnableFeignAutoRefresh
4233
@AutoConfigureAfter(ConfigurationPropertiesRebinderAutoConfiguration.class)
43-
public abstract class BaseTest<T> {
34+
public class BaseTest {
4435

45-
private static final Logger log = LoggerFactory.getLogger(BaseTest.class);
4636
@Autowired
4737
private ApplicationEventPublisher publisher;
48-
@Autowired
49-
private Environment environment;
50-
@Autowired
51-
private BaseClient client;
52-
53-
protected abstract String afterTestComponentConfigKey();
54-
protected abstract Class<? extends T> afterTestComponent();
55-
56-
public void replaceConfig() {
57-
final String key = afterTestComponentConfigKey();
58-
Set<String> keys = Collections.singleton(key);
59-
final Class<?> className = afterTestComponent();
60-
MutablePropertySources propertySources = ((ConfigurableEnvironment)this.environment).getPropertySources();
61-
Map<String, Object> map = new HashMap<>();
62-
log.trace("replacing config key {} with value {}", key, className.getName());
63-
map.put(key, className);
64-
propertySources.addFirst(new MapPropertySource("after", map));
65-
66-
EnvironmentChangeEvent event = new EnvironmentChangeEvent(keys);
67-
68-
triggerRefreshEvent();
69-
70-
this.publisher.publishEvent(event);
71-
}
72-
73-
@Test
74-
public void testInternal() {
75-
try {
76-
this.client.echo("hello", "1.0");
77-
78-
} catch (Exception ignored) {
79-
80-
}
81-
replaceConfig();
82-
try {
83-
this.client.echo("world", "1.0");
84-
} catch (Exception ignored) {
85-
86-
}
87-
88-
89-
}
9038

9139
protected void triggerRefreshEvent() {
9240
this.publisher.publishEvent(new RefreshEvent(new Object(), new Object(), "test"));

0 commit comments

Comments
 (0)