赞
踩
看完了Spring整合Dubbo中, Dubbo配置文件的加载流程;
对@Service, @Reference的加载原理好奇, 挖根刨地,虽然看不懂每处细节,但是我至少想要了解整个流程是怎么走的。
package org.apache.dubbo.demo.provider; public class Application { public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class); context.start(); System.in.read(); } @Configuration @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider") @PropertySource("classpath:/spring/dubbo-provider.properties") static class ProviderConfiguration { } } //@EnabeDubbo注解 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @EnableDubboConfig @DubboComponentScan public @interface EnableDubbo { //该属性的值也是DubboComponentScan属性basePackages的值; @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {}; @AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple") boolean multipleConfig() default true; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(DubboComponentScanRegistrar.class) public @interface DubboComponentScan { /** * basePackages属性的别名。 * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation * declarations e.g.: {@code @DubboComponentScan("org.my.pkg")} instead of * {@code @DubboComponentScan(basePackages="org.my.pkg")}. * * @return the base packages to scan */ String[] value() default {}; /** * 扫描@Service注解类的基本包路径, value属性是这个属性的别名 * Base packages to scan for annotated @Service classes. {@link #value()} is an * alias for (and mutually exclusive with) this attribute. * <p> * Use {@link #basePackageClasses()} for a type-safe alternative to String-based * package names. * * @return the base packages to scan */ String[] basePackages() default {};= //... Class<?>[] basePackageClasses() default {}; }
工作:
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { System.out.println("执行DubboComponentScanRegistrar"); // 拿到DubboComponentScan注解所定义的包路径,扫描该package下的类,识别这些类上 Set<String> packagesToScan = getPackagesToScan(importingClassMetadata); // 注册ServiceAnnotationBeanPostProcessor一个Bean // 实现了BeanDefinitionRegistryPostProcessor接口,所以在Spring启动时会调用postProcessBeanDefinitionRegistry方法 // 该方法会进行扫描,扫描@Service注解了的类,然后生成BeanDefinition(会生成两个,一个普通的bean,一个ServiceBean),后续的Spring周期中会生成Bean // 在ServiceBean中会监听ContextRefreshedEvent事件,一旦Spring启动完后,就会进行服务导出 registerServiceAnnotationBeanPostProcessor(packagesToScan, registry); // 注册ReferenceAnnotationBeanPostProcessor // 实现了AnnotationInjectedBeanPostProcessor接口,继而实现了InstantiationAwareBeanPostProcessorAdapter接口 // 所以Spring在启动时,在对属性进行注入时会调用AnnotationInjectedBeanPostProcessor接口中的postProcessPropertyValues方法 // 在这个过程中会按照@Refrence注解的信息去生成一个RefrenceBean对象 registerReferenceAnnotationBeanPostProcessor(registry); } }
工作:
private Set<String> getPackagesToScan(AnnotationMetadata metadata) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(DubboComponentScan.class.getName())); String[] basePackages = attributes.getStringArray("basePackages"); Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses"); String[] value = attributes.getStringArray("value"); // Appends value array attributes Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(value)); packagesToScan.addAll(Arrays.asList(basePackages)); for (Class<?> basePackageClass : basePackageClasses) { packagesToScan.add(ClassUtils.getPackageName(basePackageClass)); } if (packagesToScan.isEmpty()) { return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName())); } return packagesToScan; }
工作:
/** * Registers {@link ServiceAnnotationBeanPostProcessor} * * @param packagesToScan packages to scan without resolving placeholders * @param registry {@link BeanDefinitionRegistry} * @since 2.5.8 */ private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) { // 生成一个RootBeanDefinition,对应的beanClass为ServiceAnnotationBeanPostProcessor.class BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class); // 将包路径作为在构造ServiceAnnotationBeanPostProcessor时调用构造方法时的传入参数 builder.addConstructorArgValue(packagesToScan); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); }
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor { void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException; } public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware, ResourceLoaderAware, BeanClassLoaderAware { //1. 处理包名, 路径中如果有空格,就去掉; //2. 扫描包,进行Bean注册 @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan); if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) { // 扫描包,进行Bean注册 registerServiceBeans(resolvedPackagesToScan, registry); } else { if (logger.isWarnEnabled()) { logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!"); } } } 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 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 scanner.scan(packageToScan); // 查找被@Service注解的类的BeanDefinition(无论这个类有没有被@ComponentScan注解标注了) // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not. Set<BeanDefinitionHolder> beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator); if (!CollectionUtils.isEmpty(beanDefinitionHolders)) { // 扫描到BeanDefinition开始处理它 for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) { registerServiceBean(beanDefinitionHolder, registry, scanner); } //...日志 } else { //....日志 } } }
这个内容是Spring的扫描注解的内容, 我大概知道其作用,内部源码和我想象的不一样;
工作:
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>(); for (String basePackage : basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
工作:
private Set<BeanDefinitionHolder> findServiceBeanDefinitionHolders( ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry, BeanNameGenerator beanNameGenerator) { Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(packageToScan); Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<>(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, 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); /** * The {@link AnnotationAttributes} of @Service annotation */ AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false); // 服务实现类对应的接口 Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass); // 服务实现类对应的bean的名字,比如:demoServiceImpl String annotatedServiceBeanName = beanDefinitionHolder.getBeanName(); // 生成一个ServiceBean AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName); // ServiceBean Bean name ServiceBean表示服务,我们要使用一个服务应该拿ServiceBean String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass); if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean // 把ServiceBean注册进去,对应的beanName为ServiceBean:org.apache.dubbo.demo.DemoService registry.registerBeanDefinition(beanName, serviceBeanDefinition); //...日志 } else { //...日志 } }
工作 :获取服务实现类Class上的@Service注解信息;
private Annotation findServiceAnnotation(Class<?> beanClass) { Annotation service = findMergedAnnotation(beanClass, Service.class); if (service == null) { service = findMergedAnnotation(beanClass, com.alibaba.dubbo.config.annotation.Service.class); } return service; } public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) { if (!(element instanceof Class)) { //关键: 获取Class的注解@Service A annotation = element.getAnnotation(annotationType); if (annotation != null) { //返回 return AnnotationUtils.synthesizeAnnotation(annotation, element); } } AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationType, false, false); return AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element); }
作用: 创建代表ServiceBean的BeanDefinition对象;
工作:
private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation, AnnotationAttributes serviceAnnotationAttributes, Class<?> interfaceClass, String annotatedServiceBeanName) { // 生成一个ServiceBean对应的BeanDefinition BeanDefinitionBuilder 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的属性 propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames)); // References "ref" property to annotated-@Service Bean // ref属性赋值为另外一个bean, 对应的就是被@Service注解的服务实现类对应的bean addPropertyReference(builder, "ref", annotatedServiceBeanName); // Set interface builder.addPropertyValue("interface", interfaceClass.getName()); // Convert parameters into map builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters"))); // 配置了methods属性,则给ServiceBean对应的methods属性赋值 // Add methods parameters List<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(); }
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware, ApplicationEventPublisherAware { //...省略部分代码 @Override public void onApplicationEvent(ContextRefreshedEvent event) { // 当前服务没有被导出并且没有卸载,才导出服务 if (!isExported() && !isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } // 服务导出(服务注册) export(); } } } public class ServiceConfig<T> extends AbstractServiceConfig { private static final long serialVersionUID = 3033787999037024738L; private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); private static final Map<String, Integer> RANDOM_PORT_MAP = new HashMap<String, Integer>(); private static final ScheduledExecutorService DELAY_EXPORT_EXECUTOR = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true)); private final List<URL> urls = new ArrayList<URL>(); private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>(); private String interfaceName; private Class<?> interfaceClass; private T ref; private String path; private List<MethodConfig> methods; private ProviderConfig provider; private String providerIds; } public abstract class AbstractServiceConfig extends AbstractInterfaceConfig { private static final long serialVersionUID = 1L; protected String version; protected String group; protected Boolean deprecated = false; protected Integer delay; protected Boolean export; protected Integer weight; protected String document; protected Boolean dynamic = true; protected String token; protected String accesslog; protected List<ProtocolConfig> protocols; protected String protocolIds; private Integer executes; private Boolean register; private Integer warmup; private String serialization; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。