Spring
看完了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;
}
- @EnableDubboConfig是用来加载配置文件的,并将properties文件里面的配置项转换为绑定的DubboConfig配置类与DubboConfigBingdingBeanPostProcessor后置处理器类,在前置处理过程, 使用Spring的DataBinder技术,给每个DubboConfig配置类绑定值;
- @DubboComponentScan: 用来扫描@Service 和@Reference注解修饰的类;
@DubboComponentScan
@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 {};
}
- @DubboComponentScan 使用 Import注解 导入类DubboComponentScanRegistrar.class, 通过这个类完成@Service 和@Reference注解的扫描工作;
DubboComponentScanRegistrar
工作:
- 获得@DubboComponentToScan注解 定义的基础包路径,扫描基础包路径下的类。
- 注册一个ServiceAnnotationBeanPostProcessor处理器类,作用是完成处理被@Service修饰的类;
- 注册一个ReferenceAnnotationBeanPostProcessor处理器类, 作用是完成处理被@Reference注解修饰的类;
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);
}
}
getPackagesToScan(importingClassMetadata)
工作:
- 获取DubboComponentScan注解类的所有属性;
- 获取DubboComponentScan的basePackages属性值;
- 获取DubboComponentScan的basePackageClasses属性值;
- 获取DubboComponentScan的value属性值;
- 创建一个Set集合存储存储value, basePackages路径;
- 获取basePackageClass的包名路径,放入Set集合;
- 如果Set集合最后还是为空, 先获取注解所修饰的类的路径包名;
- 开头@EnableDubbo(scanBasePackages = “org.apache.dubbo.demo.provider”),我们指定了扫描的基本路径
- 如果没有配置这个路径, 就会使用 @EnabbleDubbo 所修饰的类的路径包名 作为扫描路径 即“org.apache.dubbo.demo.provider”
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;
}
registerServiceAnnotationBeanPostProcessor(packagesToScan, registry)
工作:
- 创建一个代表ServiceAnnotationBeanPostProcessor的BeanDefinitionBuilder构造器;
- 设置构造器属性 , 参数为扫描的路径集合;
- 设置Role属性, 默认为2;
- 获取代表ServiceAnnotationBeanPostProcessor的BeanDefinition;
- 注入容器;
/**
* 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);
}
ServiceAnnotationBeanPostProcessor
- 这个类名很奇怪, 第一次还以为是后置处理器, 结果发现这个类是没有实现BeanPostProcessor接口,因此,这个不是一个后置处理器;
- 该类实现BeanDefinitionRegistryPostProcessor接口, 这个接口是Bean定义注册处理器, 就是用来注册BeanDefinition的;
- 在Spring启动时, 会调用这个类的postProcessBeanDefinitionRegistry方法,扫描@Service注解所修饰的类,并作为一个Dubbo服务;
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;
}
}
registerServiceBeans(resolvedPackagesToScan, registry)
工作:
- 创建一个DubboClassPathBeanDefinitionScanner实例, dubbo的路径扫描器;
- 创建一个Bean名称生成器;
- 扫描器设置要扫描的注解, 指定为Service.class,和com.alibaba.dubbo.config.annotation.Service.class, 后者为了兼容处理;
- 遍历扫描包路径集合;
4.1 scanner.scan(packageToScan) 扫描Dubbo自定义的@Service注解, 并将扫描到的Dubbo服务转换为BeanDefinition实例注入容器;
4.2 findServiceBeanDefinitionHolders查找路径下所有被@Service注解所修饰的类的BeanDefinition;
4.3 遍历BeanDefinition
4.4 生成一个ServiceBean实例,并注入容器;
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 {
//....日志
}
}
}
ClassPathBeanDefinitionScanner#doScan
这个内容是Spring的扫描注解的内容, 我大概知道其作用,内部源码和我想象的不一样;
工作:
- 创建返回结果beanDefinitions的Set集合
- 遍历包路径
- findCandidateComponents扫描候选的组件,返回一个BeanDefinition集合;
- 遍历返回的BeanDefinition集合;
- 将BeanDefinition转换为BeanDefinitionHolder实例, 然后registerBeanDefinition方法注入容器;
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;
}
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator)
工作:
- 使用扫描器对包路径下的服务进行扫描,扫描到的Dubbo服务类都会转换为一个Bean Definition类 (是否重复了这个过程,上面就已经执行了一次,有点疑问)
- 创建一个Set集合存储结果
- 遍历 扫描的BeanDefinition类
- 转换为BeanDefinitionHolder类, 加入Set集合结果;
- 返回;
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;
}
registerServiceBean(beanDefinitionHolder, registry, scanner)
工作:
- 获取BeanDefinitionHolder代表的Dubbo服务实现类;
- 获取@Service注解对象实例; (@Service(protocol , version …) 注解里面可以指定多个属性)
- 获取@Service注解对象实例的所有的属性值;
- 获取实现类实现的接口;
- 获取服务实现类的Bean名称;DemoServiceImpl类的bean名称为demoServiceImpl…
- 创建一个代表serviceBean的BeanDefinition实例;
- 获取一个ServiceBean的Bean名称, (以类名+组名+版本号为名称)
- 判断容器中是否已经存在,不存在就注入容器;
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 {
//...日志
}
}
findServiceAnnotation(beanClass)
工作 :获取服务实现类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);
}
buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName)
作用: 创建代表ServiceBean的BeanDefinition对象;
工作:
- 生成一个ServiceBean对应的BeanDefinition
- 获取ServiceBean的普通属性MutablePropertyValues (像String,Long…)
- 从@Service注解的配置值 赋值给ServiceBean的属性;
- 设置ref属性, ref属性 引用 Dubbo服务实现类实例;
4.1 Spring的内容: Spring根据传入的Bean名称,从容器中拿到Bean,拿不到就进行创建, 然后返回, 然后ServiceBean的ref属性引用Bean实例; - ServiceBean的属性"provider", “monitor”, “application”, “module”, “registry”, “protocol”,“interface”, “interfaceName”, "parameters"赋值,
这些属性都不是普通属性, 而是类对象, 例如application对应得DubboApplicationConfig, protocol对应得ProtocolConfig依次类推,Spring中使用addPropertyValue进行赋值; - 最终返回代表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();
}
ServiceBean
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;
}
- 重要配置属性:
ServiceBean表示一个Dubbo服务,它有一些参数,比如:
- ref,表示服务的具体实现类
- interface,表示服务的接口
- parameters,表示服务的参数(@Service注解中所配置的信息)
- application,表示服务所属的应用
- protocols,表示服务所使用的协议
- registries,表示服务所要注册的注册中心
- ServiceBean本身实现了ApplicationListener监听器接口, 当Spring应用启动完后,Bean全部加载完毕, Dubbo的所有服务都会进行导出,例如注册到注册中心等操作;
结果
- Dubbo整合Spring过程中, 扫描@Service注解和所修饰的类时, 会生成代表服务实现类的BeanDefinition,并注入容器;
- 对于Dubbo来说此时得到的Bean是一个服务, 因此Dubbo需要解析@Service注解所包含的信息, 解析@Service注解后,会另外生成一个代表ServiceBean的BeanDefinition, 并注入容器;