Skip to content

Commit c1f88b8

Browse files
@RetrofitClient、@Retry等注解支持元注解、继承以及@AliasFor
1 parent 7c28a09 commit c1f88b8

25 files changed

+262
-54
lines changed

README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter]
4141
- [x] [全局拦截器](#全局拦截器)
4242
- [x] [调用适配器](#调用适配器)
4343
- [x] [数据转换器](#数据转码器)
44+
- [x] [元注解](#元注解)
4445
- [x] [其他功能示例](#其他功能示例)
4546

4647
## 快速使用
@@ -51,7 +52,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter]
5152
<dependency>
5253
<groupId>com.github.lianjiatech</groupId>
5354
<artifactId>retrofit-spring-boot-starter</artifactId>
54-
<version>2.3.1</version>
55+
<version>2.3.2</version>
5556
</dependency>
5657
```
5758

@@ -64,7 +65,7 @@ gitee项目地址:[https://gitee.com/lianjiatech/retrofit-spring-boot-starter]
6465
<dependency>
6566
<groupId>com.github.lianjiatech</groupId>
6667
<artifactId>retrofit-spring-boot-starter</artifactId>
67-
<version>2.3.1</version>
68+
<version>2.3.2</version>
6869
</dependency>
6970
<dependency>
7071
<groupId>com.squareup.okhttp3</groupId>
@@ -854,6 +855,29 @@ retrofit:
854855

855856
针对每个Java接口,还可以通过`@RetrofitClient`注解的`converterFactories()`指定当前接口采用的`Converter.Factory`,指定的转换器工厂实例依然优先从Spring容器获取。
856857

858+
### 元注解
859+
860+
`@RetrofitClient`、`@Retry`、`@Logging`、`@Resilience4jDegrade`等注解支持元注解、继承以及`@AliasFor`。 我们可以随意组合、调整相关注解:
861+
862+
```java
863+
864+
@Retention(RetentionPolicy.RUNTIME)
865+
@Target(ElementType.TYPE)
866+
@Documented
867+
@Inherited
868+
@RetrofitClient(baseUrl = "${test.baseUrl}")
869+
@Logging(logLevel = LogLevel.WARN)
870+
@Retry(intervalMs = 200)
871+
public @interface MyRetrofitClient {
872+
873+
@AliasFor(annotation = RetrofitClient.class, attribute = "converterFactories")
874+
Class<? extends Converter.Factory>[] converterFactories() default {GsonConverterFactory.class};
875+
876+
@AliasFor(annotation = Logging.class, attribute = "logStrategy")
877+
LogStrategy logStrategy() default LogStrategy.BODY;
878+
}
879+
```
880+
857881
## 其他功能示例
858882

859883
### form参数接口调用

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.github.lianjiatech</groupId>
88
<artifactId>retrofit-spring-boot-starter</artifactId>
9-
<version>2.3.1</version>
9+
<version>2.3.2</version>
1010

1111
<name>retrofit-spring-boot-starter</name>
1212
<description>retrofit-spring-boot-starter</description>

src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitFactoryBean.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
import java.util.HashMap;
1111
import java.util.List;
1212
import java.util.Map;
13+
import java.util.Objects;
1314
import java.util.concurrent.TimeUnit;
1415

1516
import org.springframework.beans.BeansException;
1617
import org.springframework.beans.factory.FactoryBean;
1718
import org.springframework.context.ApplicationContext;
1819
import org.springframework.context.ApplicationContextAware;
1920
import org.springframework.context.EnvironmentAware;
21+
import org.springframework.core.annotation.AnnotatedElementUtils;
2022
import org.springframework.core.annotation.AnnotationUtils;
2123
import org.springframework.core.env.Environment;
2224
import org.springframework.util.Assert;
@@ -87,7 +89,8 @@ public boolean isSingleton() {
8789
}
8890

8991
private okhttp3.ConnectionPool parseConnectionPool() {
90-
RetrofitClient retrofitClient = retrofitInterface.getAnnotation(RetrofitClient.class);
92+
RetrofitClient retrofitClient =
93+
AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, RetrofitClient.class);
9194
String poolName = retrofitClient.poolName();
9295
Map<String, ConnectionPool> poolRegistry = retrofitConfigBean.getPoolRegistry();
9396
Assert.notNull(poolRegistry, "poolRegistry does not exist! Please set retrofitConfigBean.poolRegistry!");
@@ -99,7 +102,8 @@ private okhttp3.ConnectionPool parseConnectionPool() {
99102

100103
private OkHttpClient createOkHttpClient() throws IllegalAccessException, InvocationTargetException {
101104
OkHttpClient.Builder okHttpClientBuilder = createOkHttpClientBuilder();
102-
RetrofitClient retrofitClient = retrofitInterface.getAnnotation(RetrofitClient.class);
105+
RetrofitClient retrofitClient =
106+
AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, RetrofitClient.class);
103107
if (isEnableDegrade(retrofitInterface)) {
104108
okHttpClientBuilder.addInterceptor(retrofitConfigBean.getRetrofitDegrade());
105109
}
@@ -116,7 +120,8 @@ private OkHttpClient createOkHttpClient() throws IllegalAccessException, Invocat
116120
}
117121

118122
private OkHttpClient.Builder createOkHttpClientBuilder() throws InvocationTargetException, IllegalAccessException {
119-
RetrofitClient retrofitClient = retrofitInterface.getAnnotation(RetrofitClient.class);
123+
RetrofitClient retrofitClient =
124+
AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, RetrofitClient.class);
120125
Method method = findOkHttpClientBuilderMethod();
121126
if (method != null) {
122127
return (OkHttpClient.Builder)method.invoke(null);
@@ -158,11 +163,11 @@ private Method findOkHttpClientBuilderMethod() {
158163

159164
@SuppressWarnings("unchecked")
160165
private List<Interceptor> findInterceptorByAnnotation() {
161-
Annotation[] classAnnotations = retrofitInterface.getAnnotations();
166+
Annotation[] classAnnotations = AnnotationUtils.getAnnotations(retrofitInterface);
162167
List<Interceptor> interceptors = new ArrayList<>();
163168
// 找出被@InterceptMark标记的注解。Find the annotation marked by @InterceptMark
164169
List<Annotation> interceptAnnotations = new ArrayList<>();
165-
for (Annotation classAnnotation : classAnnotations) {
170+
for (Annotation classAnnotation : Objects.requireNonNull(classAnnotations)) {
166171
Class<? extends Annotation> annotationType = classAnnotation.annotationType();
167172
if (annotationType.isAnnotationPresent(InterceptMark.class)) {
168173
interceptAnnotations.add(classAnnotation);
@@ -204,9 +209,9 @@ private List<Interceptor> findInterceptorByAnnotation() {
204209
return interceptors;
205210
}
206211

207-
private Retrofit createRetrofit()
208-
throws InstantiationException, IllegalAccessException, InvocationTargetException {
209-
RetrofitClient retrofitClient = retrofitInterface.getAnnotation(RetrofitClient.class);
212+
private Retrofit createRetrofit() throws IllegalAccessException, InvocationTargetException {
213+
RetrofitClient retrofitClient =
214+
AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, RetrofitClient.class);
210215
String baseUrl = RetrofitUtils.convertBaseUrl(retrofitClient, retrofitClient.baseUrl(), environment);
211216

212217
OkHttpClient client = createOkHttpClient();

src/main/java/com/github/lianjiatech/retrofit/spring/boot/core/RetrofitScan.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.lang.annotation.Documented;
44
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Inherited;
56
import java.lang.annotation.Retention;
67
import java.lang.annotation.RetentionPolicy;
78
import java.lang.annotation.Target;
@@ -15,6 +16,7 @@
1516
@Target(ElementType.TYPE)
1617
@Documented
1718
@Import(RetrofitClientScannerRegistrar.class)
19+
@Inherited
1820
public @interface RetrofitScan {
1921

2022
/**

src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/BaseRetrofitDegrade.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.concurrent.ConcurrentHashMap;
77

88
import org.springframework.context.EnvironmentAware;
9+
import org.springframework.core.annotation.AnnotatedElementUtils;
910
import org.springframework.core.env.Environment;
1011

1112
import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient;
@@ -29,7 +30,8 @@ public String parseResourceName(Method method) {
2930
if (resourceName != null) {
3031
return resourceName;
3132
}
32-
RetrofitClient retrofitClient = method.getDeclaringClass().getAnnotation(RetrofitClient.class);
33+
RetrofitClient retrofitClient =
34+
AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), RetrofitClient.class);
3335
String baseUrl = RetrofitUtils.convertBaseUrl(retrofitClient, retrofitClient.baseUrl(), environment);
3436
HttpMethodPath httpMethodPath = parseHttpMethodPath(method);
3537
resourceName = formatResourceName(baseUrl, httpMethodPath);

src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/DegradeProxy.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.lang.reflect.Proxy;
66

77
import org.springframework.context.ApplicationContext;
8+
import org.springframework.core.annotation.AnnotatedElementUtils;
89

910
import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient;
1011

@@ -22,7 +23,8 @@ public class DegradeProxy implements InvocationHandler {
2223

2324
@SuppressWarnings("unchecked")
2425
public static <T> T create(Object source, Class<T> retrofitInterface, ApplicationContext applicationContext) {
25-
RetrofitClient retrofitClient = retrofitInterface.getAnnotation(RetrofitClient.class);
26+
RetrofitClient retrofitClient =
27+
AnnotatedElementUtils.findMergedAnnotation(retrofitInterface, RetrofitClient.class);
2628
Class<?> fallbackClass = retrofitClient.fallback();
2729
Object fallback = null;
2830
if (!void.class.isAssignableFrom(fallbackClass)) {

src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/ResourceNameParser.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,38 +30,38 @@ public interface ResourceNameParser {
3030
*/
3131
default HttpMethodPath parseHttpMethodPath(Method method) {
3232

33-
if (method.isAnnotationPresent(HTTP.class)) {
34-
HTTP http = method.getAnnotation(HTTP.class);
33+
HTTP http = method.getAnnotation(HTTP.class);
34+
if (http != null) {
3535
return new HttpMethodPath(http.method(), http.path());
3636
}
3737

38-
if (method.isAnnotationPresent(GET.class)) {
39-
GET get = method.getAnnotation(GET.class);
38+
GET get = method.getAnnotation(GET.class);
39+
if (get != null) {
4040
return new HttpMethodPath("GET", get.value());
4141
}
4242

43-
if (method.isAnnotationPresent(POST.class)) {
44-
POST post = method.getAnnotation(POST.class);
43+
POST post = method.getAnnotation(POST.class);
44+
if (post != null) {
4545
return new HttpMethodPath("POST", post.value());
4646
}
4747

48-
if (method.isAnnotationPresent(PUT.class)) {
49-
PUT put = method.getAnnotation(PUT.class);
48+
PUT put = method.getAnnotation(PUT.class);
49+
if (put != null) {
5050
return new HttpMethodPath("PUT", put.value());
5151
}
5252

53-
if (method.isAnnotationPresent(DELETE.class)) {
54-
DELETE delete = method.getAnnotation(DELETE.class);
53+
DELETE delete = method.getAnnotation(DELETE.class);
54+
if (delete != null) {
5555
return new HttpMethodPath("DELETE", delete.value());
5656
}
5757

58-
if (method.isAnnotationPresent(HEAD.class)) {
59-
HEAD head = method.getAnnotation(HEAD.class);
58+
HEAD head = method.getAnnotation(HEAD.class);
59+
if (head != null) {
6060
return new HttpMethodPath("HEAD", head.value());
6161
}
6262

63-
if (method.isAnnotationPresent(PATCH.class)) {
64-
PATCH patch = method.getAnnotation(PATCH.class);
63+
PATCH patch = method.getAnnotation(PATCH.class);
64+
if (patch != null) {
6565
return new HttpMethodPath("PATCH", patch.value());
6666
}
6767
throw new UnsupportedOperationException("unsupported method!" + method);

src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/resilience4j/Resilience4jRetrofitDegrade.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ public void loadDegradeRules(Class<?> retrofitInterface) {
4343
continue;
4444
}
4545
Resilience4jDegrade resilience4jDegrade =
46-
AnnotationExtendUtils.findAnnotationIncludeClass(method, Resilience4jDegrade.class);
46+
AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(),
47+
Resilience4jDegrade.class);
4748
if (resilience4jDegrade == null) {
4849
continue;
4950
}

src/main/java/com/github/lianjiatech/retrofit/spring/boot/degrade/sentinel/SentinelRetrofitDegrade.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ public void loadDegradeRules(Class<?> retrofitInterface) {
4242
}
4343
// 获取熔断配置
4444
SentinelDegrade sentinelDegrade =
45-
AnnotationExtendUtils.findAnnotationIncludeClass(method, SentinelDegrade.class);
45+
AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(),
46+
SentinelDegrade.class);
4647
if (sentinelDegrade == null) {
4748
continue;
4849
}
@@ -61,7 +62,8 @@ public void loadDegradeRules(Class<?> retrofitInterface) {
6162
public Response intercept(Chain chain) throws IOException {
6263
Request request = chain.request();
6364
Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
64-
if (AnnotationExtendUtils.findAnnotationIncludeClass(method, SentinelDegrade.class) == null) {
65+
if (AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(),
66+
SentinelDegrade.class) == null) {
6567
return chain.proceed(request);
6668
}
6769
String resourceName = parseResourceName(method);

src/main/java/com/github/lianjiatech/retrofit/spring/boot/interceptor/ErrorDecoderInterceptor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.springframework.beans.BeansException;
88
import org.springframework.context.ApplicationContext;
99
import org.springframework.context.ApplicationContextAware;
10+
import org.springframework.core.annotation.AnnotatedElementUtils;
1011

1112
import com.github.lianjiatech.retrofit.spring.boot.core.ErrorDecoder;
1213
import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient;
@@ -30,7 +31,8 @@ public class ErrorDecoderInterceptor implements Interceptor, ApplicationContextA
3031
public Response intercept(Chain chain) throws IOException {
3132
Request request = chain.request();
3233
Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
33-
RetrofitClient retrofitClient = method.getDeclaringClass().getAnnotation(RetrofitClient.class);
34+
RetrofitClient retrofitClient =
35+
AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), RetrofitClient.class);
3436
ErrorDecoder errorDecoder =
3537
AppContextUtils.getBeanOrNew(applicationContext, retrofitClient.errorDecoder());
3638
boolean decoded = false;

src/main/java/com/github/lianjiatech/retrofit/spring/boot/interceptor/ServiceChooseInterceptor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.net.URI;
66
import java.util.Objects;
77

8+
import org.springframework.core.annotation.AnnotatedElementUtils;
89
import org.springframework.util.StringUtils;
910

1011
import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient;
@@ -32,7 +33,8 @@ public Response intercept(Chain chain) throws IOException {
3233
Request request = chain.request();
3334
Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
3435
Class<?> declaringClass = method.getDeclaringClass();
35-
RetrofitClient retrofitClient = declaringClass.getAnnotation(RetrofitClient.class);
36+
RetrofitClient retrofitClient =
37+
AnnotatedElementUtils.findMergedAnnotation(declaringClass, RetrofitClient.class);
3638
String baseUrl = retrofitClient.baseUrl();
3739
if (StringUtils.hasText(baseUrl)) {
3840
return chain.proceed(request);

src/main/java/com/github/lianjiatech/retrofit/spring/boot/log/LoggingInterceptor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.lang.reflect.Method;
55
import java.util.Objects;
66

7+
import org.springframework.core.annotation.AnnotatedElementUtils;
8+
79
import com.github.lianjiatech.retrofit.spring.boot.config.LogProperty;
810

911
import lombok.extern.slf4j.Slf4j;
@@ -30,8 +32,7 @@ public LoggingInterceptor(LogProperty logProperty) {
3032
public Response intercept(Chain chain) throws IOException {
3133
Request request = chain.request();
3234
Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
33-
// 获取重试配置
34-
Logging logging = method.getDeclaringClass().getAnnotation(Logging.class);
35+
Logging logging = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Logging.class);
3536
if (!needLog(logging)) {
3637
return chain.proceed(request);
3738
}

src/main/java/com/github/lianjiatech/retrofit/spring/boot/retry/RetryInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public Response intercept(Chain chain) throws IOException {
3333
Request request = chain.request();
3434
Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
3535
// 获取重试配置
36-
Retry retry = AnnotationExtendUtils.findAnnotationIncludeClass(method, Retry.class);
36+
Retry retry = AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(), Retry.class);
3737
if (!needRetry(retry)) {
3838
return chain.proceed(request);
3939
}

src/main/java/com/github/lianjiatech/retrofit/spring/boot/util/AnnotationExtendUtils.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.lang.annotation.Annotation;
44
import java.lang.reflect.Method;
55

6+
import org.springframework.core.annotation.AnnotatedElementUtils;
7+
68
import lombok.experimental.UtilityClass;
79

810
/**
@@ -16,15 +18,17 @@ public class AnnotationExtendUtils {
1618
* 查找方法及其类上的指定注解,优先返回方法上的。
1719
* @param <A> 注解泛型参数
1820
* @param method 方法
21+
* @param clazz 类型
1922
* @param annotationType 注解类型
2023
* @return 方法及其类上的指定注解。
2124
*/
22-
public static <A extends Annotation> A findAnnotationIncludeClass(Method method, Class<A> annotationType) {
23-
A annotation = method.getAnnotation(annotationType);
25+
public static <A extends Annotation> A findMergedAnnotation(Method method, Class<?> clazz,
26+
Class<A> annotationType) {
27+
A annotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);
2428
if (annotation != null) {
2529
return annotation;
2630
}
27-
return method.getDeclaringClass().getAnnotation(annotationType);
31+
return AnnotatedElementUtils.findMergedAnnotation(clazz, annotationType);
2832
}
2933

3034
/**
@@ -36,11 +40,11 @@ public static <A extends Annotation> A findAnnotationIncludeClass(Method method,
3640
*/
3741
public static <A extends Annotation> boolean isAnnotationPresentIncludeMethod(Class<?> clazz,
3842
Class<A> annotationType) {
39-
if (clazz.isAnnotationPresent(annotationType)) {
43+
if (AnnotatedElementUtils.findMergedAnnotation(clazz, annotationType) != null) {
4044
return true;
4145
}
4246
for (Method method : clazz.getMethods()) {
43-
if (method.isAnnotationPresent(annotationType)) {
47+
if (AnnotatedElementUtils.findMergedAnnotation(method, annotationType) != null) {
4448
return true;
4549
}
4650
}

0 commit comments

Comments
 (0)