1.概要
本文示例是扫描接口上的自定义注解,并为接口生成相应代理类,模拟FeignClient
2.代码
2.1 启动类上注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(HttpClientBeanDefinitionRegistrar.class)
public @interface EnableHttpClient {
}
2.2 自定义注解(用于接口上)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HttpClient {
String address();//域名
}
2.3自定义get请求注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GetRequest {
String value();//请求路径
}
2.4 自定义扫描类
public class HttpScanHandler extends ClassPathBeanDefinitionScanner {
public HttpScanHandler(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
super(registry, useDefaultFilters);
}
@Override
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
addIncludeFilter(new AnnotationTypeFilter(HttpClient.class));
Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
if(CollectionUtil.isNotEmpty(beanDefinitionHolders)){
beanDefinitionHolders.forEach(beanDefinitionHolder -> {
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();
try {
Class<?> aClass = Class.forName(beanDefinition.getBeanClassName());
String address = aClass.getAnnotation(HttpClient.class).address();
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(aClass);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(address);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
beanDefinition.setBeanClass(HttpFactory.class);
beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
});
}
return beanDefinitionHolders;
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
}
}
2.5 自定义ImportBeanDefinitionRegistrar
public class HttpClientBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
HttpScanHandler scanHandle = new HttpScanHandler(beanDefinitionRegistry,false);
scanHandle.doScan(ClassUtils.getPackageName(annotationMetadata.getClassName()));
}
}
2.6 启动类
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableHttpClient
public class SpringRegisterApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRegisterApplication.class, args);
}
}
2.7 工厂类
public class HttpFactory implements FactoryBean<Object> {
private final Class<?> interFace;
private final String address;
public HttpFactory(Class<?> interFace,String address) {
this.interFace = interFace;
this.address = address;
}
@Override
public Object getObject() {
return Proxy.newProxyInstance(interFace.getClassLoader(),new Class[]{interFace},new HttpProxyHandler(address));
}
@Override
public Class<?> getObjectType() {
return interFace;
}
}
2.8 代理类
@Slf4j
public class HttpProxyHandler implements InvocationHandler {
private String address;
public HttpProxyHandler(String address) {
this.address = address;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String query = method.getAnnotation(GetRequest.class).value();
Map<String,String> map = new HashMap<>();
map.put("question","1111");
String s = HttpClient.doGet(address + query, map, null);
return null;
}
}
3.示例
@HttpClient(address = "http://localhost:8080")
public interface HttpInterface {
@GetRequest("/test/getNluResult")
void run();
}
@Slf4j
@Service
public class BeanServiceImpl implements BeanService {
@Resource
private HttpInterface httpInterface;
@Override
public void k() {
httpInterface.run();
}
}
简单模拟了FeignClient请求,有问题的小伙伴可以留言