一、声明式编程的好处
声明式编程的好处有:
- 代码简洁,不需要写很多相同的实现代码
- 对使用者屏蔽了实现细节,使用者只需要声明要做什么,而不关心怎么做。
二、适用场景
声明式编程适合封装公共的,不涉及业务逻辑的基础服务,例如远程调用,数据库访问。
三、Spring中声明式编程的实现
下面看一个在Spring中通过声明式编程实现远程访问的Demo,Demo类结构如下:
- EnableRestClients是一个Spring的启动类注解,用来声明是否要开启此功能,如果有此注解则开启,否则不开启。
- RestClient是要声明的远程接口的类注解,用来声明这些接口是否要实现远程调用。
- RestClientPath是要声明的远程接口的方法注解,用来声明该方法要调用的远程地址。
- RestClientsRegistrar是一个注册类,作用是动态注册远程接口的实现类。
- RestClientFactoryBean是一个工厂Bean,作用是将远程接口的实现作为一个Bean注册到Spring中。
- RestClientProxyFactory是一个代理工厂,用于生成远程接口的代理类。
- RestClientProxy是远程接口的代理类,调用远程接口方法时,实际调用的是代理类。
下面看下代码:
1.EnableRestClients.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RestClientsRegistrar.class)
public @interface EnableRestClients {
/**
* 要扫描的接口类的包名
*
* @return
*/
String[] basePackages() default {
};
}
2.RestClient.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RestClient {
}
3.RestClientPath.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface RestClientPath {
/**
* 出于示例简单考虑,只有一个远程访问地址URL
*
* @return
*/
String url() default "";
}
4.RestClientsRegistrar核心代码
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
System.out.println("this.resourceLoader: " + this.resourceLoader);
// 添加一个注解过滤器,有RestClient注解的类/接口才继续处理
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(RestClient.class);
scanner.addIncludeFilter(annotationTypeFilter);
// 这里的metadata是spring启动类上的注解元数据,下面这一步是获取EnableRestClients注解的属性
Map