dubbo service注解用法_Dubbo的服务暴露与服务消费原理(2)-基于注解配置原理解析...

用注解的方式启动Spring容器

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配置文件中的,作用为:配置spring容器(应用上下文)

@Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的,作用为:注册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 packagesToScan = getPackagesToScan(importingClassMetadata);

registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

registerReferenceAnnotationBeanPostProcessor(registry);

}

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值