Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge dev branch #44

Merged
merged 1 commit into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ io.microsphere.spring.cloud.client.service.registry.autoconfigure.ServiceRegistr
io.microsphere.spring.cloud.client.service.registry.autoconfigure.WebMvcServiceRegistryAutoConfiguration
io.microsphere.spring.cloud.client.service.registry.autoconfigure.WebFluxServiceRegistryAutoConfiguration
io.microsphere.spring.cloud.client.service.registry.autoconfigure.SimpleAutoServiceRegistrationAutoConfiguration
io.microsphere.spring.cloud.client.service.registry.actuate.autoconfigure.ServiceRegistrationEndpointAutoConfiguration
io.microsphere.spring.cloud.client.service.registry.actuate.autoconfigure.ServiceRegistrationEndpointAutoConfiguration
io.microsphere.spring.cloud.fault.tolerance.tomcat.autoconfigure.TomcatFaultToleranceAutoConfiguration
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;

Expand Down Expand Up @@ -41,9 +40,6 @@ public class SimpleAutoServiceRegistrationAutoConfigurationTest {
@Autowired
private SimpleAutoServiceRegistration simpleAutoServiceRegistration;

@LocalServerPort
private Integer port;

@Test
public void test() {
assertEquals("test-service", registration.getServiceId());
Expand All @@ -52,7 +48,6 @@ public void test() {
assertNotNull(registration.getUri());
assertNotNull(registration.getInstanceId());
assertNotNull(registration.getMetadata());
assertNotNull(port);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
Expand All @@ -19,6 +20,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Inherited
@Import(EnableFeignAutoRefresh.Marker.class)
public @interface EnableFeignAutoRefresh {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import io.microsphere.spring.cloud.openfeign.autorefresh.FeignComponentRegistry;
import io.microsphere.spring.cloud.openfeign.components.NoOpRequestInterceptor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.openfeign.FeignBuilderCustomizer;
import org.springframework.cloud.openfeign.FeignClientProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;

/**
* The Auto-Configuration class for {@link EnableFeignAutoRefresh}
Expand All @@ -20,7 +21,6 @@
* @since 0.0.1
*/
@ConditionalOnBean(EnableFeignAutoRefresh.Marker.class)
@AutoConfigureAfter(ConfigurationPropertiesRebinderAutoConfiguration.class)
public class FeignClientAutoRefreshAutoConfiguration {

@Bean
Expand All @@ -30,9 +30,12 @@ public FeignBuilderCustomizer addDefaultRequestInterceptorCustomizer() {
};
}

@Bean
public FeignClientConfigurationChangedListener feignClientConfigurationChangedListener(FeignComponentRegistry registry) {
return new FeignClientConfigurationChangedListener(registry);
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReadyEvent(ApplicationReadyEvent event) {
/**
* Make sure the FeignClientConfigurationChangedListener is registered after the ConfigurationPropertiesRebinder
*/
registerFeignClientConfigurationChangedListener(event);
}

@Bean
Expand All @@ -45,4 +48,10 @@ public FeignClientSpecificationPostProcessor feignClientSpecificationPostProcess
return new FeignClientSpecificationPostProcessor();
}

private void registerFeignClientConfigurationChangedListener(ApplicationReadyEvent event) {
ConfigurableApplicationContext context = event.getApplicationContext();
FeignComponentRegistry feignComponentRegistry = context.getBean(FeignComponentRegistry.class);
context.addApplicationListener(new FeignClientConfigurationChangedListener(feignComponentRegistry));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
public class AutoRefreshCapability implements Capability, ApplicationContextAware {

private final FeignComponentRegistry componentRegistry;

private final FeignContext feignContext;

private final FeignClientProperties clientProperties;

private String contextId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ public FeignClientConfigurationChangedListener(FeignComponentRegistry registry)
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
Map<String, Set<String>> effectiveClients = resolveChangedClient(event);
effectiveClients.forEach(registry::refresh);

if (!effectiveClients.isEmpty()) {
effectiveClients.forEach(registry::refresh);
}
}

protected Map<String, Set<String>> resolveChangedClient(EnvironmentChangeEvent event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
Expand All @@ -29,6 +30,10 @@ public CompositedRequestInterceptor(String contextId, BeanFactory beanFactory) {
this.contextId = contextId;
}

public Set<RequestInterceptor> getRequestInterceptors() {
return Collections.unmodifiableSet(set);
}


@Override
public void apply(RequestTemplate template) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @author <a href="mailto:[email protected]">韩超</a>
* @since 0.0.1
*/
@FeignClient(contextId = "my-client", name = "my-client")
@FeignClient(contextId = "my-client", name = "my-client", configuration = {MockCapability.class})
public interface BaseClient {

@GetMapping("echo")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.endpoint.event.RefreshEvent;
import org.springframework.cloud.openfeign.EnableFeignClients;
Expand All @@ -31,14 +28,17 @@
@TestPropertySource(properties = {
"spring.main.allow-bean-definition-overriding=true",
"feign.client.config.default.encoder=io.microsphere.spring.cloud.openfeign.encoder.AEncoder",
"feign.client.config.default.error-decoder=io.microsphere.spring.cloud.openfeign.errordecoder.AErrorDecoder",
"feign.client.config.default.query-map-encoder=io.microsphere.spring.cloud.openfeign.querymapencoder.AQueryMapEncoder",
"feign.client.config.default.retryer=io.microsphere.spring.cloud.openfeign.retryer.ARetry",
"feign.client.config.default.decoder=io.microsphere.spring.cloud.openfeign.decoder.ADecoder",
"feign.client.config.default.request-interceptors[0]=io.microsphere.spring.cloud.openfeign.requestInterceptor.ARequestInterceptor",
"feign.client.config.default.default-request-headers.app=my-app",
"feign.client.config.default.default-query-parameters.sign=my-sign",
})
@ComponentScan(basePackages = "io.microsphere.spring.cloud.openfeign")
@EnableFeignClients(clients = BaseClient.class)
@EnableFeignAutoRefresh
@AutoConfigureAfter(ConfigurationPropertiesRebinderAutoConfiguration.class)
public abstract class BaseTest<T> {

private static final Logger log = LoggerFactory.getLogger(BaseTest.class);
Expand All @@ -50,7 +50,9 @@ public abstract class BaseTest<T> {
private BaseClient client;

protected abstract String afterTestComponentConfigKey();
protected abstract Class<? extends T> beforeTestComponentClass();
protected abstract Class<? extends T> afterTestComponent();
protected abstract FeignComponentAssert<T> loadFeignComponentAssert();

public void replaceConfig() {
final String key = afterTestComponentConfigKey();
Expand All @@ -71,20 +73,21 @@ public void replaceConfig() {

@Test
public void testInternal() {
ObservableFeignInvocationHandler.componentAssert = loadFeignComponentAssert();

ObservableFeignInvocationHandler.expectComponentClass = beforeTestComponentClass();
try {
this.client.echo("hello", "1.0");

} catch (Exception ignored) {

}
replaceConfig();

ObservableFeignInvocationHandler.expectComponentClass = afterTestComponent();
try {
this.client.echo("world", "1.0");
} catch (Exception ignored) {

}


}

protected void triggerRefreshEvent() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.microsphere.spring.cloud.openfeign;

import feign.InvocationHandlerFactory;

/**
* @author <a href="mailto:[email protected]">韩超</a>
* @since 0.0.1
*/
public abstract class FeignComponentAssert<T> {


protected abstract T loadCurrentComponent(InvocationHandlerFactory.MethodHandler methodHandler) throws Exception;

public boolean expect(InvocationHandlerFactory.MethodHandler methodHandler, Class<T> expectedClass) throws Exception {
T component = loadCurrentComponent(methodHandler);
return expectedClass.equals(component.getClass());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.microsphere.spring.cloud.openfeign;

import feign.Capability;
import feign.InvocationHandlerFactory;

/**
* @author <a href="mailto:[email protected]">韩超</a>
* @since 0.0.1
*/
public class MockCapability implements Capability {

@Override
public InvocationHandlerFactory enrich(InvocationHandlerFactory invocationHandlerFactory) {
return ObservableFeignInvocationHandler::new;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.microsphere.spring.cloud.openfeign;

import feign.InvocationHandlerFactory;
import feign.Target;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

import static feign.Util.checkNotNull;

/**
* @author <a href="mailto:[email protected]">韩超</a>
* @since 0.0.1
*/
public class ObservableFeignInvocationHandler implements InvocationHandler {


private static final Logger log = LoggerFactory.getLogger(ObservableFeignInvocationHandler.class);
public static FeignComponentAssert<?> componentAssert;
public static Class expectComponentClass;

private final Target target;
private final Map<Method, InvocationHandlerFactory.MethodHandler> dispatch;

ObservableFeignInvocationHandler(Target target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch) {
this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("equals".equals(method.getName())) {
try {
Object otherHandler =
args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
return equals(otherHandler);
} catch (IllegalArgumentException e) {
return false;
}
} else if ("hashCode".equals(method.getName())) {
return hashCode();
} else if ("toString".equals(method.getName())) {
return toString();
} else if (!dispatch.containsKey(method)) {
throw new UnsupportedOperationException(
String.format("Method \"%s\" should not be called", method.getName()));
}

InvocationHandlerFactory.MethodHandler methodHandler = dispatch.get(method);
Assert.isTrue(componentAssert.expect(methodHandler, expectComponentClass), "unexpected component");
log.info("component validation is True");
return dispatch.get(method).invoke(args);
}

@Override
public boolean equals(Object obj) {
if (obj instanceof ObservableFeignInvocationHandler) {
ObservableFeignInvocationHandler other = (ObservableFeignInvocationHandler) obj;
return target.equals(other.target);
}
return false;
}

@Override
public int hashCode() {
return target.hashCode();
}

@Override
public String toString() {
return target.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.microsphere.spring.cloud.openfeign.decoder;

import feign.FeignException;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;

import java.io.IOException;
import java.lang.reflect.Type;

/**
* @author <a href="mailto:[email protected]">韩超</a>
* @since 0.0.1
*/
public class ADecoder implements Decoder {

@Override
public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.microsphere.spring.cloud.openfeign.decoder;

import feign.FeignException;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;

import java.io.IOException;
import java.lang.reflect.Type;

/**
* @author <a href="mailto:[email protected]">韩超</a>
* @since 0.0.1
*/
public class BDecoder implements Decoder {

@Override
public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
return null;
}
}
Loading
Loading