将不可实例化的Interface动态代理后注册到Spring容器以便IOC,用于便捷的生成Local Stub
在业务中整合中间件或三方依赖时,常借助Client/SDK进行命令式过程式的调用,相关代码散落各处,既不OOP也不方便追溯和维护。本项目通过对Interface进行便捷透明的代理并注册到Spring容器,方便业务中使用Interface和Annotation作为DSL封装各类简洁易用易维护的本地存根。
- Spring-boot 2.x
本项目依赖
Spring-Boot 2.0.8
核心基础API开发测试,且没有传递Spring-Boot依赖,理论上兼容所有Spring-Boot版本。
- Java8
已发布到中央仓库,GAV坐标如下:
<dependency>
<groupId>com.github.yungyu16.spring</groupId>
<artifactId>spring-boot-starter-proxy</artifactId>
<version>release-tag</version>
</dependency>
查看release-tag
在maven中查看
本项目借助AutoConfiguration实现了零配置,开箱即用;默认扫描的basePackages为 @SpringBootApplication
入口类所在包。
如需添加自定义扫描路径,请使用 @ProxyStubScan
注解配置,该注解使用方式和 @ComponentScan
类似。
两种使用方式:
- 最小化原生配置,直接使用本项目提供的标记注解,简单快捷。
- 语义化定制配置,基于Spring元注解模型定制语义化标记注解,提高可读性并可以传递额外上下文,查看示例。
两种代理方式:
- 指定方法拦截器(
com.github.yungyu16.spring.stub.annotation.ProxyStub#dispatcherType
)
使用默认的代理工厂生成代理类,拦截方法调用并回调指定的InvocationDispatcher - 指定代理工厂(
com.github.yungyu16.spring.stub.annotation.ProxyStub#factoryType
)
使用指定的代理工厂生成代理类,可自行选择动态代理方案,方便进行更底层的定制。可参考我的这个项目
- 继承
AbstractInvocationDispatcher<ANNOTATION_TYPE extends Annotation, ATTACHMENT>
按需重载invoke
方法。
@Component
public class InvocationDispatcherImpl extends AbstractInvocationDispatcher<ProxyStub, Void> {
@Override
protected Object invoke(StubContext<ProxyStub> stubProxyContext, Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(stubProxyContext.getAnnotation());
System.out.println("InvocationDispatcherImpl");
return null;
}
}
- 定义Interface并添加标记注解指定InvocationDispatcher
@ProxyStub(InvocationDispatcherImpl.class)
public interface HelloService {
void hello();
}
- IOC注入使用
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloServiceTest {
@Autowired
private HelloService helloService;
@Test
public void testHello() {
helloService.hello();
}
}
- 继承
AbstractInvocationDispatcher<ANNOTATION_TYPE extends Annotation, ATTACHMENT>
按需重载invoke
方法。
@Component
public class InvocationDispatcherImpl extends AbstractInvocationDispatcher<TestClient, Void> {
@Override
protected Object invoke(StubContext<TestClient> stubProxyContext, Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(stubProxyContext.getAnnotation());
System.out.println("InvocationDispatcherImpl");
return null;
}
}
- 定制语义化注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ProxyStub(InvocationDispatcherImpl.class)
public @interface TestClient {
@AliasFor(annotation = ProxyStub.class, attribute = "beanName")
String value() default "";
}
- 定义Interface并添加标记注解指定InvocationDispatcher
@TestClient("helloService")
public interface HelloService {
void hello();
}
- IOC注入使用
@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloServiceTest {
@Autowired
private HelloService helloService;
@Test
public void testHello() {
helloService.hello();
}
}