> anoyi中的GrpcAutoConfiguration
1. 简述
这个方法是读取端口ip配置并执行启动grpc的核心方法
2. 查看GrpcAutoConfiguration的注解
~~~
@Slf4j
@Configuration
@EnableConfigurationProperties(GrpcProperties.class)
~~~
这三个注解,一个slf4j日志,代表可以直接调用日志对象,一个是Configuration,代表是ico的配置类,一个是EnableConfigurationProperties,会自己动注入配置的实体
3. 分析GrpcProperties类
~~~
@Data
@ConfigurationProperties(prefix = "spring.grpc")
public class GrpcProperties {
/**
* enable server start
*/
private boolean enable;
/**
* server listen port
*/
private int port;
/**
* client config
*/
private List<RemoteServer> remoteServers;
/**
* client interceptor
*/
private Class clientInterceptor;
/**
* server interceptor
*/
private Class serverInterceptor;
}
~~~
这个类头部有个两个注解类,一个是Data代表该类自己生成get和set方法,一个是ConfigurationProperties,代表会去拿jvm里面的Properties的key前缀符合(prefix = "spring.grpc")的属性,并实例化GrpcProperties ,把Properties符合条件的value值注入同名的属性中。
4. 查看属性
~~~
private final AbstractApplicationContext applicationContext;
private final GrpcProperties grpcProperties;
~~~
applicationContext是全局上下文的spring context,在构造方法调用的时候回自动注入,grpcProperties是在构造方法的时候自动注入
5. 查看构造方法(这个方法交给spring实例化,具体查看Configuration这个注解,这个注解会在ico容器初始化)
~~~
public GrpcAutoConfiguration(AbstractApplicationContext applicationContext, GrpcProperties grpcProperties) {
this.applicationContext = applicationContext;
this.grpcProperties = grpcProperties;
}
~~~
6. 一些bean的实现
~~~
/**
* 全局 RPC 序列化/反序列化
*/
@Bean
@ConditionalOnMissingBean(SerializeService.class)
public SerializeService serializeService() {
return new SofaHessianSerializeService();
}
/**
* PRC 服务调用
*/
@Bean
public CommonService commonService(SerializeService serializeService) {
return new CommonService(applicationContext, serializeService);
}
/**
* RPC 服务端
*/
@Bean
@ConditionalOnMissingBean(GrpcServer.class)
@ConditionalOnProperty(value = "spring.grpc.enable", havingValue = "true")
public GrpcServer grpcServer(CommonService commonService) throws Exception {
GrpcServer server = new GrpcServer(grpcProperties, commonService);
server.start();
return server;
}
/**
* RPC 客户端
*/
@Bean
@ConditionalOnMissingBean(GrpcClient.class)
public GrpcClient grpcClient(SerializeService serializeService) {
GrpcClient client = new GrpcClient(grpcProperties, serializeService);
client.init();
return client;
}
~~~
ConditionalOnMissingBean意思是相应的配置的类如果不存在就不调用注解它的方法,ConditionalOnProperty注解的意思是必须满足配置的value的相对应的Properties的value值等于havingValue 的值才能执行注解它的方法
7. 查看ExternalGrpcServiceScannerRegistrar类
~~~
/**
* 手动扫描 @GrpcService 注解的接口,生成动态代理类,注入到 Spring 容器
*/
public static class ExternalGrpcServiceScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
private BeanFactory beanFactory;
private ResourceLoader resourceLoader;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
ClassPathBeanDefinitionScanner scanner = new ClassPathGrpcServiceScanner(registry);
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(GrpcService.class));
Set<BeanDefinition> beanDefinitions = scanPackages(importingClassMetadata, scanner);
ProxyUtil.registerBeans(beanFactory, beanDefinitions);
}
/**
* 包扫描
*/
private Set<BeanDefinition> scanPackages(AnnotationMetadata importingClassMetadata, ClassPathBeanDefinitionScanner scanner) {
List<String> packages = new ArrayList<>();
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(GrpcServiceScan.class.getCanonicalName());
if (annotationAttributes != null) {
String[] basePackages = (String[]) annotationAttributes.get("packages");
if (basePackages.length > 0) {
packages.addAll(Arrays.asList(basePackages));
}
}
Set<BeanDefinition> beanDefinitions = new HashSet<>();
if (CollectionUtils.isEmpty(packages)) {
return beanDefinitions;
}
packages.forEach(pack -> beanDefinitions.addAll(scanner.findCandidateComponents(pack)));
return beanDefinitions;
}
}
protected static class ClassPathGrpcServiceScanner extends ClassPathBeanDefinitionScanner {
ClassPathGrpcServiceScanner(BeanDefinitionRegistry registry) {
super(registry, false);
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
}
}
~~~
这个类在import注解配置中,所以会在spring启动的时候初始化该类,该类实现了
BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware这三个类,
BeanFactoryAware提供bean工厂,
ImportBeanDefinitionRegistrar提供扫描包时候调用的registerBeanDefinitions方法,
ResourceLoaderAware提供setResourceLoader的方法
registerBeanDefinitions这个方法在spring启动时候调用,
8. 查看registerBeanDefinitions方法
~~~
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
ClassPathBeanDefinitionScanner scanner = new ClassPathGrpcServiceScanner(registry);
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(GrpcService.class));
Set<BeanDefinition> beanDefinitions = scanPackages(importingClassMetadata, scanner);
ProxyUtil.registerBeans(beanFactory, beanDefinitions);
}
~~~
这个方法有两个参数AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,importingClassMetadata这个参数可以取得import注解的父注解的参数,registry是bean注册器,
ClassPathGrpcServiceScanner是继承ClassPathBeanDefinitionScanner的方法,这里new这个对象,并重构
isCandidateComponent的方法,这个是过滤类的方法,下面查看ClassPathGrpcServiceScanner类
~~~
protected static class ClassPathGrpcServiceScanner extends ClassPathBeanDefinitionScanner {
ClassPathGrpcServiceScanner(BeanDefinitionRegistry registry) {
super(registry, false);
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
}
}
~~~
这个类很简单,然后registerBeanDefinitions这个方法会执行下面两句语句,这个只是把扫描器添加过滤器,过滤掉没有GrpcService注解的类
~~~
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(GrpcService.class));
~~~
接下来registerBeanDefinitions方法会调用
~~~
Set<BeanDefinition> beanDefinitions = scanPackages(importingClassMetadata, scanner);
~~~
这个scanPackages可以扫描出符合条件的BeanDefinition,具体scanPackages方法,可以看下面
~~~
/**
* 包扫描
*/
private Set<BeanDefinition> scanPackages(AnnotationMetadata importingClassMetadata, ClassPathBeanDefinitionScanner scanner) {
List<String> packages = new ArrayList<>();
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(GrpcServiceScan.class.getCanonicalName());
if (annotationAttributes != null) {
String[] basePackages = (String[]) annotationAttributes.get("packages");
if (basePackages.length > 0) {
packages.addAll(Arrays.asList(basePackages));
}
}
Set<BeanDefinition> beanDefinitions = new HashSet<>();
if (CollectionUtils.isEmpty(packages)) {
return beanDefinitions;
}
packages.forEach(pack -> beanDefinitions.addAll(scanner.findCandidateComponents(pack)));
return beanDefinitions;
}
~~~
这个scanPackages方法只是扫描符合ClassPathBeanDefinitionScanner 扫描器标准的packages包底下的类,并生成
BeanDefinition,接下来registerBeanDefinitions方法会调用ProxyUtil.registerBeans(beanFactory, beanDefinitions);这是代理的方法,接下来看看这个代理类
9. 查看ProxyUtil类
~~~
protected static class ProxyUtil {
static void registerBeans(BeanFactory beanFactory, Set<BeanDefinition> beanDefinitions) {
for (BeanDefinition beanDefinition : beanDefinitions) {
String className = beanDefinition.getBeanClassName();
if (StringUtils.isEmpty(className)) {
continue;
}
try {
// 创建代理类
Class<?> target = Class.forName(className);
Object invoker = new Object();
InvocationHandler invocationHandler = new GrpcServiceProxy<>(target, invoker);
Object proxy = Proxy.newProxyInstance(GrpcService.class.getClassLoader(), new Class[]{target}, invocationHandler);
// 注册到 Spring 容器
String beanName = ClassNameUtils.beanName(className);
((DefaultListableBeanFactory) beanFactory).registerSingleton(beanName, proxy);
} catch (ClassNotFoundException e) {
log.warn("class not found : " + className);
}
}
}
}
~~~
这个类具体看registerBeans方法,这个方法有两个参数BeanFactory beanFactory, Set<BeanDefinition> beanDefinitions,beanFactory是bean工厂,beanDefinitions是我们上面扫描的类,看样子是要实例化bean了
接下来看看
```
InvocationHandler invocationHandler = new GrpcServiceProxy<>(target, invoker);
```
这个是实例化代理类,并传入被代理类invoker,也就是我们的bean,然后是执行下面的方法
```
Object proxy = Proxy.newProxyInstance(GrpcService.class.getClassLoader(), new Class[]{target}, invocationHandler);
```
这个是调用动态代理newProxyInstance方法,返回invoker这个实例化的类,但是这时候动态代理可能已经重写invoker这个的所有方法,实现aop了,具体怎么样我们也不知道,也就是proxy 已经不是原本的类,接下来看下一步
```
String beanName = ClassNameUtils.beanName(className);
((DefaultListableBeanFactory) beanFactory).registerSingleton(beanName, proxy);
```
这里把我们的代理类注册到spring bean中