在2.5.4版本中,我们通常使用以下方式启动dubbo应用
public static void main(String[] args) {
com.alibaba.dubbo.container.Main.main(args);
}
深入这个方法,其实核心的代码是这一段
public void start() {
String configPath = ConfigUtils.getProperty(SPRING_CONFIG);
if (configPath == null || configPath.length() == 0) {
configPath = DEFAULT_SPRING_CONFIG;
}
context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false);
context.addApplicationListener(new DubboApplicationListener());
context.registerShutdownHook();
context.refresh();
context.start();
}
可以看到,其实还启动了spring的ClassPathXmlApplicationContext,并添加了一个DubboApplicationListener。更细的内容先放放,再看看在2.5.8版本后的基于annotation的启动方式:
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
context.start();
System.in.read();
}
这里除了换成创建AnnotationConfigApplicationContext意外,特别的就是这个ProviderConfiguration
@Configuration
@EnableDubbo(scanBasePackages = "com.alibaba.dubbo.samples.impl")
@PropertySource("classpath:/spring/dubbo-provider.properties")
public class ProviderConfiguration {
}
是不是和sprinBoot的风格很像,相比之前的xml配置方式,是不是清爽了很多?
下面顺便也把provider中的service以及consumer中的reference一并贴一下,方便大家阅读:
@Component("annotatedConsumer")
public class GreetingServiceConsumer {
@Reference
private GreetingService greetingService;
public String doSayHello(String name) {
return greetingService.sayHello(name);
}
}
@Service
public class AnnotatedGreetingService implements GreetingService {
public String sayHello(String name) {
System.out.println("greeting service received: " + name);
return "hello, " + name;
}
}
除了@Service和@Reference两个Dubbo的标注,就没有其他框架层面的代码了,大大减少我们配置的工作量。
回到我们的主题,知道了程序启动的入口,也知道其实都是通过spring容器来加载dubbo的Service的,那么Service是怎么加载并初始化的呢,这里分成两个阶段来介绍,一个是Service定义的加载;另一个是Service对象的实例化;
Service定义的加载
先来看看这个类
/**
* {@link Service} Annotation
* {@link BeanDefinitionRegistryPostProcessor Bean Definition Registry Post Processor}
*
* @since 2.5.8
*/
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
ResourceLoaderAware, BeanClassLoaderAware {
...
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
// 核心方法是这个
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
/**
* 注册被 {@link Service}标注的类的Bean(此Bean是Service类的定义)
*
* @param packagesToScan The base packages to scan
* @param registry {@link BeanDefinitionRegistry}
*/
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
for (String packageToScan : packagesToScan) {
// Registers @Service Bean first
scanner.scan(packageToScan);
// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
Set<BeanDefinitionHolder> beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
// 解析生成Service的定义Bean,并注册到spring容器中
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
}
}
}
...
}
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Service service = findAnnotation(beanClass, Service.class);
Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
// 解析Service类的注解,创建RootBeanDefinition对象,对象的beanClass属性值为ServiceBean
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
// 注册ServcieBean到spring容器中
registry.registerBeanDefinition(beanName, serviceBeanDefinition);
...
}
未完待续...