ProviderConfiguration是自定义的启动类。
public class AnnotationProviderMain { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class); context.start(); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } }
在我的启动类AnnotationProviderMain中调用了AnnotationConfigApplicationContext(Class... annotatedClasses)构造方法,在这个构造方法里面,又调用了AnnotationConfigApplicationContext无参构造方法。无参构造方法中实例化了AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。
public AnnotationConfigApplicationContext(Class... annotatedClasses) { this(); this.register(annotatedClasses); this.refresh(); } public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } public void register(Class... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); this.reader.register(annotatedClasses); }
调用了AnnotatedBeanDefinitionReader的registerBean方法
public void register(Class... annotatedClasses) { Class[] var2 = annotatedClasses; int var3 = annotatedClasses.length; for(int var4 = 0; var4 < var3; ++var4) { Class<?> annotatedClass = var2[var4]; this.registerBean(annotatedClass); } } public void registerBean(Class<?> annotatedClass) { this.registerBean(annotatedClass, (String)null, (Class[])null); } public void registerBean(Class<?> annotatedClass, String name, Class... qualifiers) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null) { Class[] var7 = qualifiers; int var8 = qualifiers.length; for(int var9 = 0; var9 < var8; ++var9) { Class<? extends Annotation> qualifier = var7[var9]; if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); } }
来看看BeanDefinitionReaderUtils的registerBeanDefinition方法。通过(beanName, bean)和(beanName, alias别名)的方式注册bean。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); String[] aliases = definitionHolder.getAliases(); if (aliases != null) { String[] var4 = aliases; int var5 = aliases.length; for(int var6 = 0; var6 < var5; ++var6) { String alias = var4[var6]; registry.registerAlias(beanName, alias); } } } public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); } private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); return (Environment)(registry instanceof EnvironmentCapable ? ((EnvironmentCapable)registry).getEnvironment() : new StandardEnvironment()); }
@Configuration @EnableDubbo(scanBasePackages = "gdut.ff.provider") public class ProviderConfiguration { //提供者配置 @Bean public ProviderConfig providerConfig() { return new ProviderConfig(); } //应用信息配置 @Bean public ApplicationConfig applicationConfig() { ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("annotation-provider"); return applicationConfig; } //注册中心配置 @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setProtocol("zookeeper"); registryConfig.setAddress("127.0.0.1"); registryConfig.setPort(2181); return registryConfig; } //协议配置 @Bean public ProtocolConfig protocolConfig() { ProtocolConfig protocolConfig = new ProtocolConfig(); protocolConfig.setName("dubbo"); protocolConfig.setPort(20880); return protocolConfig; } }
自定义的ProviderConfiguration使用了两个注解,一个是Configuration,另一个是EnableDubbo。
@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,作用为:配置spring容器(应用上下文)
@Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的<bean>,作用为:注册bean对象
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { String value() default ""; }
/** * 能使Dubbo components像Spring Beans一样,是DubboComponentScan和EnableDubboConfig的结合 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @EnableDubboConfig @DubboComponentScan public @interface EnableDubbo { /** * 定义扫描注解@Service的包 * 使用类型安全的scanBasePackageClasses()替代基于字符串的包名称 * @return 扫描的包 */ @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; /** *scanBasePackages()的类型安全替代方案,用于指定要扫描带注释的@Service类的程序包。 指定类别的包将被扫描。 *return 从包中扫描的类 */ @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {}; /** * 它指示AbstractConfig是否绑定到多个Spring Bean。 * return 返回默认值false */ @AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple") boolean multipleConfig() default false; }
@EnableDubbo使用了两个注解@EnableDubboConfig和@DubboComponentScan
ConfugurationClassParser的processImports方法调用了DubboConfigConfigurationSelector.selectImports()方法
@EnableDubboConfig根据multiple返回的布尔值,来决定绑定的bean的属性前缀。若为true,表示多个Bean绑定的属性前缀,如果是false,表示单个Bean绑定的属性前缀。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @Import(DubboConfigConfigurationSelector.class) public @interface EnableDubboConfig { /** * 是否绑定多个Bean */ boolean multiple() default false; }
Beanmultiple的值 | false | true |
---|---|---|
ApplicationConfig | dubbo.application | dubbo.applications |
ModuleConfig | dubbo.module | dubbo.modules |
RegistryConfig | dubbo.registry | dubbo.registries |
ProtocolConfig | dubbo.protocol | dubbo.protocols |
MonitorConfig | dubbo.monitor | dubbo.monitors |
ProviderConfig | dubbo.provider | dubbo.providers |
ConsumerConfig | dubbo.consumer | dubbo.consumers |
@EnableDubboConfig还使用了@Import(DubboConfigConfigurationSelector.class)注解
来看看DubboConfigConfigurationSelector类的
selectImports方法。获取EnableDubboConfig的属性multiple的值,
public String[] selectImports(AnnotationMetadata importingClassMetadata) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName())); boolean multiple = attributes.getBoolean("multiple"); if (multiple) { return of(DubboConfigConfiguration.Multiple.class.getName()); } else { return of(DubboConfigConfiguration.Single.class.getName()); } }
来看看DubboConfigConfiguration的实现
public class DubboConfigConfiguration { /** * Single Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class) }) public static class Single { } /** * Multiple Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true) }) public static class Multiple { } }
再来看看@EnableDubboConfigBindings的实现
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(DubboConfigBindingsRegistrar.class) public @interface EnableDubboConfigBindings { /** * The value of {@link EnableDubboConfigBindings} * * @return non-null */ EnableDubboConfigBinding[] value(); }
调用了DubboConfigBindingsRegistrar。
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBindings.class.getName())); //获取EnableDubboConfigBindings注解全部的value值。 AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value"); DubboConfigBindingRegistrar registrar = new DubboConfigBindingRegistrar(); registrar.setEnvironment(environment); for (AnnotationAttributes element : annotationAttributes) { //注册到Spring容器。 registrar.registerBeanDefinitions(element, registry); } }
@DubboComponentScan调用了DubboComponentScanRegistrar注解,会生成ServiceAnnotationBeanPostProcessor和ReferenceAnnotationBeanPostProcessor
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { Set<String> packagesToScan = getPackagesToScan(importingClassMetadata); registerServiceAnnotationBeanPostProcessor(packagesToScan, registry); registerReferenceAnnotationBeanPostProcessor(registry); }
《深入理解Apache Dubbo与实战》
https://blog.csdn.net/u014199...