赞
踩
继续上篇内容,本篇讲解服务启动时,动态注入相关的实例。
自定义的注解分为三部分:
@EnableRainRpc 自动扫包,引入一些默认配置,以及注入RainRpcComponentScanRegistrar,使注解了@RainProvider, @RainConsumer 的类生效。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import({RainRpcComponentScanRegistrar.class, RainRpcConfig.class,RainRpcAutoConfiguration.class }) public @interface EnableRainRpc { /** * 指定扫描包路径 */ String[] value() default {}; /** * 指定扫描类 */ Class<?>[] basePackageClasses() default {}; }
@RainProvider 用于标识服务提供者的具体实现类
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Inherited
public @interface RainProvider {
}
@RainConsumer标识服务提供者的接口,用于消费者引用
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Inherited public @interface RainConsumer { /** * 应用名称 */ String name() default ""; /** * 服务集群名称 */ String cluster() default "rpc"; /** * 降级处理 */ String degradation() default ""; /** * 请求等待 */ long timeout() default 10; }
RainRpcComponentScanRegistrar 实现了spring的ImportBeanDefinitionRegistrar 接口,可以动态注册
beanDefinition。容器启动时,会执行registerBeanDefinitions方法。
public class RainRpcComponentScanRegistrar implements ImportBeanDefinitionRegistrar , ResourceLoaderAware , EnvironmentAware, BeanClassLoaderAware { protected final Log logger = LogFactory.getLog(getClass()); private ResourceLoader resourceLoader; private Environment environment; private ClassLoader classLoader; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 获取要扫包的路径 Set<String> packagesToScan = getPackagesToScan(importingClassMetadata); // 处理@RainProvider registerProviderBeanPostProcessor(packagesToScan, registry); // 处理@RainConsumer registerConsumerBeanPostProcessor(packagesToScan,registry); } /** * 注册RainProvider注解处理器 * @author wu * @param packagesToScan * @param registry * @return */ public void registerProviderBeanPostProcessor(Set<String> packagesToScan,BeanDefinitionRegistry registry) { BeanDefinitionBuilder builder = rootBeanDefinition(RainProviderBeanPostProcessor.class); builder.addConstructorArgValue(packagesToScan); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); } /** * 注册RainConsumer注册处理器 * @author wu * @param registry * @return */ public void registerConsumerBeanPostProcessor(Set<String> packagesToScan,BeanDefinitionRegistry registry) { ClassPathScanningCandidateComponentProvider scanner = getScanner(); scanner.setResourceLoader(this.resourceLoader); scanner.addIncludeFilter(new AnnotationTypeFilter(RainConsumer.class)); for (String basePackage : packagesToScan) { Set<BeanDefinition> candidateComponents = scanner .findCandidateComponents(basePackage); for (BeanDefinition candidateComponent : candidateComponents) { if (candidateComponent instanceof AnnotatedBeanDefinition) { // verify annotated class is an interface AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent; AnnotationMetadata annotationMetadata = beanDefinition.getMetadata(); if (!annotationMetadata.isInterface()) { logger.info("@RainConsumer can only be specified on an interface"); continue; } registerClient(beanDefinition, registry); } } } } private void registerClient(AnnotatedBeanDefinition beanDefinition, BeanDefinitionRegistry registry) { Class<?> beanClass = resolveClass(beanDefinition); RainConsumer service = findAnnotation(beanClass, RainConsumer.class); AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, beanClass); registry.registerBeanDefinition(beanClass.getName(), serviceBeanDefinition); } private AbstractBeanDefinition buildServiceBeanDefinition(RainConsumer service, Class<?> interfaceClass) { BeanDefinitionBuilder builder = rootBeanDefinition(ConsumerBean.class); builder.addPropertyValue("interfaceClass", interfaceClass.getName()); builder.addPropertyValue("annotation", service); builder.setPrimary(Boolean.TRUE); return builder.getBeanDefinition(); } private Class<?> resolveClass(AnnotatedBeanDefinition beanDefinition) { String beanClassName = beanDefinition.getBeanClassName(); return resolveClassName(beanClassName, classLoader); } /** * 获取扫描包路径 * @author wu * @param metadata * @return {@link Set< String>} */ private Set<String> getPackagesToScan(AnnotationMetadata metadata) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(EnableRainRpc.class.getName())); Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses"); String[] value = attributes.getStringArray("value"); // Appends value array attributes Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(value)); for (Class<?> basePackageClass : basePackageClasses) { packagesToScan.add(ClassUtils.getPackageName(basePackageClass)); } if (packagesToScan.isEmpty()) { return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName())); } return packagesToScan; } protected ClassPathScanningCandidateComponentProvider getScanner() { return new ClassPathScanningCandidateComponentProvider(false, this.environment) { @Override protected boolean isCandidateComponent( AnnotatedBeanDefinition beanDefinition) { boolean isCandidate = false; if (beanDefinition.getMetadata().isIndependent()) { if (!beanDefinition.getMetadata().isAnnotation()) { isCandidate = true; } } return isCandidate; } }; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } }
registerProviderBeanPostProcessor方法主要是向bean注册器中注册RainProviderBeanPostProcessor后置处理器。
RainProviderBeanPostProcessor处理流程:
public class RainProviderBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware , BeanClassLoaderAware { protected final Log logger = LogFactory.getLog(getClass()); private final Set<String> packagesToScan; private Environment environment; private ClassLoader classLoader; public RainProviderBeanPostProcessor(Collection<String> packagesToScan) { this(new LinkedHashSet<>(packagesToScan)); } public RainProviderBeanPostProcessor(Set<String> packagesToScan) { this.packagesToScan = packagesToScan; } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan); if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) { registerServiceBeans(resolvedPackagesToScan, registry); } } private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) { ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false); BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry); scanner.setBeanNameGenerator(beanNameGenerator); scanner.addIncludeFilter(new AnnotationTypeFilter(RainProvider.class)); // 扫描包,注册beanDefinition for (String packageToScan : packagesToScan) { scanner.scan(packageToScan); Set<BeanDefinitionHolder> beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator); if (!CollectionUtils.isEmpty(beanDefinitionHolders)) { for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) { registerServiceBean(beanDefinitionHolder, registry); } } } } private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) { BeanNameGenerator beanNameGenerator = null; if (registry instanceof SingletonBeanRegistry) { SingletonBeanRegistry singletonBeanRegistry = SingletonBeanRegistry.class.cast(registry); beanNameGenerator = (BeanNameGenerator) singletonBeanRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); } if (beanNameGenerator == null) { if (logger.isInfoEnabled()) { logger.info("BeanNameGenerator bean can't be found in BeanFactory with name [" + CONFIGURATION_BEAN_NAME_GENERATOR + "]"); logger.info("BeanNameGenerator will be a instance of " + AnnotationBeanNameGenerator.class.getName() + " , it maybe a potential problem on bean name generation."); } beanNameGenerator = new AnnotationBeanNameGenerator(); } return beanNameGenerator; } private Set<BeanDefinitionHolder> findServiceBeanDefinitionHolders( ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry, BeanNameGenerator beanNameGenerator) { Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(packageToScan); Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<BeanDefinitionHolder>(beanDefinitions.size()); for (BeanDefinition beanDefinition : beanDefinitions) { String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry); BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName); beanDefinitionHolders.add(beanDefinitionHolder); } return beanDefinitionHolders; } private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry) { Class<?> beanClass = resolveClass(beanDefinitionHolder); RainProvider service = findAnnotation(beanClass, RainProvider.class); // 接口类 Class<?> interfaceClass = beanClass.getInterfaces()[0]; // 实现类名 String annotatedServiceBeanName = beanDefinitionHolder.getBeanName(); AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName); registry.registerBeanDefinition( interfaceClass.getName(), serviceBeanDefinition); } private Class<?> resolveClass(BeanDefinitionHolder beanDefinitionHolder) { BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition(); String beanClassName = beanDefinition.getBeanClassName(); return resolveClassName(beanClassName, classLoader); } private Set<String> resolvePackagesToScan(Set<String> packagesToScan) { Set<String> resolvedPackagesToScan = new LinkedHashSet<String>(packagesToScan.size()); for (String packageToScan : packagesToScan) { if (StringUtils.hasText(packageToScan)) { String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan.trim()); resolvedPackagesToScan.add(resolvedPackageToScan); } } return resolvedPackagesToScan; } private AbstractBeanDefinition buildServiceBeanDefinition(RainProvider service, Class<?> interfaceClass, String annotatedServiceBeanName) { BeanDefinitionBuilder builder = rootBeanDefinition(ProviderBean.class); // 引用具体实现类 addPropertyReference(builder, "ref", annotatedServiceBeanName); builder.addPropertyValue("interfaceClass", interfaceClass.getName()); builder.addPropertyValue("methodList", interfaceClass.getDeclaredMethods()); return builder.getBeanDefinition(); } private void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, String beanName) { String resolvedBeanName = environment.resolvePlaceholders(beanName); builder.addPropertyReference(propertyName, resolvedBeanName); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } }
区别于@RainProvider的处理方式,@RainConsumer的处理换了一种方式,为啥会这样呢?
@RainConsumer注解对象都是接口,直接使用ClassPathBeanDefinitionScanner扫描器,不会将接口类转换为beanDefinition,故而不能使用beanDefinition后置处理器处理。
既然现成的扫描器实现不了目标,那就自定义一个扫描器,重写判断条件。
代码如下:
protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
@Override
protected boolean isCandidateComponent(
AnnotatedBeanDefinition beanDefinition) {
boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent()) {
if (!beanDefinition.getMetadata().isAnnotation()) {
isCandidate = true;
}
}
return isCandidate;
}
};
}
有了扫描器之后,操作方式就跟@RainProvider类似:
这里ConsumerBean是一个FactoryBean,用于连接服务,生成代理服务类。
RainRpcAutoConfiguration 向容器中注入ProviderContextStart。ProviderContextStart用于向注册中心注册服务。
@Configuration
public class RainRpcAutoConfiguration {
@Bean
public ProviderContextStart providerContextStart() {
return new ProviderContextStart();
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。