Dubbo2.7详解( 四 )

【4】扫描@Service注解,并且进行处理
汇总说明:实际上便是通过处理器扫描@Service注解的类,生成两个Bean【类对应的普通Bean,与Dubbo中要用到的ServiceBean】
其中ServiceBean,是先根据注解上的信息填充对应的属性,后采用环境变量中获取配置的属性,来完成属性填充 。
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,ResourceLoaderAware, BeanClassLoaderAware {...//核心方法1@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {// 扫描包 , 进行Bean注册,核心方法2调用registerServiceBeans(resolvedPackagesToScan, registry);} else {if (logger.isWarnEnabled()) {logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");}}}//核心方法2private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);scanner.setBeanNameGenerator(beanNameGenerator);// 扫描被Service注解标注的类scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));scanner.addIncludeFilter(new AnnotationTypeFilter(com.alibaba.dubbo.config.annotation.Service.class));for (String packageToScan : packagesToScan) {// Registers @Service Bean first// 扫描Dubbo自定义的@Service注解scanner.scan(packageToScan);// 查找被@Service注解的类的BeanDefinition(无论这个类有没有被@ComponentScan注解标注了)Set<BeanDefinitionHolder> beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {// 扫描到BeanDefinition开始处理它,核心方法3的调用for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {registerServiceBean(beanDefinitionHolder, registry, scanner);}if (logger.isInfoEnabled()) { logger.info(b...); }} else {if (logger.isWarnEnabled()) { logger.warn(...); }}}}//核心方法3private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry, DubboClassPathBeanDefinitionScanner scanner) {// 处理扫描到的每一个BeanDefinition// 1. 得到@Service注解上所配置的参数// 2. 根据每一个BeanDefinition会再额外的生成一个ServiceBean// 3. 对于每一个被@Service注解的类(服务的实现类),会生成两个Bean,一个服务实现类对应的Bean(普通Bean,和@Component一样) , 一个ServiceBean(Dubbo中要用到的Bean,因为在ServiceBean中包括了很的Config)// 具体的服务实现类Class<?> beanClass = resolveClass(beanDefinitionHolder);// @Service可以对服务进行各种配置Annotation service = findServiceAnnotation(beanClass);AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);// 服务实现类对应的接口Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);// 服务实现类对应的bean的名字 , 比如:demoServiceImplString annotatedServiceBeanName = beanDefinitionHolder.getBeanName();// 生成一个ServiceBean , 核心方法4的调用AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);// ServiceBean Bean nameServiceBean表示服务,我们要使用一个服务应该拿ServiceBeanString beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean// 把ServiceBean注册进去 , 对应的beanName为ServiceBean:org.apache.dubbo.demo.DemoServiceregistry.registerBeanDefinition(beanName, serviceBeanDefinition);if (logger.isInfoEnabled()) { logger.info(..); }} else {if (logger.isWarnEnabled()) { logger.warn(...); }}}...//核心方法4private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation,AnnotationAttributes serviceAnnotationAttributes,Class<?> interfaceClass,String annotatedServiceBeanName) {// 生成一个ServiceBean对应的BeanDefinitionBeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol","interface", "interfaceName", "parameters");// 把serviceAnnotation中的参数值赋值给ServiceBean的属性// 如:@Service(test = "test")propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames));// References "ref" property to annotated-@Service Bean// 如:@Service(protocol = "P1") , 这种就是要根据对应的值找到对应的P1的config对象里面的值// ref属性赋值为另外一个bean, 对应的就是被@Service注解的服务实现类对应的beanaddPropertyReference(builder, "ref", annotatedServiceBeanName);// Set interfacebuilder.addPropertyValue("interface", interfaceClass.getName());// Convert parameters into mapbuilder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters")));// 配置了methods属性,则给ServiceBean对应的methods属性赋值// Add methods parametersList<MethodConfig> methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods"));if (!methodConfigs.isEmpty()) {builder.addPropertyValue("methods", methodConfigs);}/*** Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference*/String providerConfigBeanName = serviceAnnotationAttributes.getString("provider");if (StringUtils.hasText(providerConfigBeanName)) {addPropertyReference(builder, "provider", providerConfigBeanName);}/*** Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference*/String monitorConfigBeanName = serviceAnnotationAttributes.getString("monitor");if (StringUtils.hasText(monitorConfigBeanName)) {addPropertyReference(builder, "monitor", monitorConfigBeanName);}/*** Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference*/String applicationConfigBeanName = serviceAnnotationAttributes.getString("application");if (StringUtils.hasText(applicationConfigBeanName)) {addPropertyReference(builder, "application", applicationConfigBeanName);}/*** Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference*/String moduleConfigBeanName = serviceAnnotationAttributes.getString("module");if (StringUtils.hasText(moduleConfigBeanName)) {addPropertyReference(builder, "module", moduleConfigBeanName);}/*** Add {@link org.apache.dubbo.config.RegistryConfig} Bean reference* 获取注解上配置的注册中心的beanName*/String[] registryConfigBeanNames = serviceAnnotationAttributes.getStringArray("registry");List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);if (!registryRuntimeBeanReferences.isEmpty()) {builder.addPropertyValue("registries", registryRuntimeBeanReferences);}/*** Add {@link org.apache.dubbo.config.ProtocolConfig} Bean reference*/String[] protocolConfigBeanNames = serviceAnnotationAttributes.getStringArray("protocol");List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);if (!protocolRuntimeBeanReferences.isEmpty()) {builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);}return builder.getBeanDefinition();}....}

推荐阅读