更好的阅读体验:Dubbo源码解析之@DubboService、@DubboReference(Dubbo源码一)
视频讲解:https://www.bilibili.com/video/BV1nBsMejEbL
对于Dubbo用的最多的就是@DubboService、@DubboReference,与之对应的就是服务的提供方、调用方。
之所以加上注解就可以运行,定是生成了代理对象,这篇文章就来讲讲如何基于这两个注解生成代理对象。
不管是服务端还是客户端,在使用Dubbo的时候都会先使用@EnableDubbo
,比如下面的demo
@SpringBootApplication
@EnableDubbo
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@EnableDubbo 是一个组合注解,它头上还有@DubboComponentScan和@EnableDubboConfig,它们就是分别来解析@DubboService、@DubboReference
EnableDubbo
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {}
DubboComponentScan
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {}
EnableDubboConfig
@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {}
一、@DubboReference 注解解析
DubboConfigConfigurationRegistrar 里面注入了一个bean处理器 ReferenceAnnotationBeanPostProcessor,这个处理器会把带有下面三个注解的bean代理成一个 ReferenceBean
- DubboReference
- Reference
- com.alibaba.dubbo.config.annotation.Reference
1、入口
入口跳的很多,全部把代码复制过来阅读体验不好,也全无必要,这里给出每个方法的关键代码
EnableDubbo
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {}
EnableDubboConfig
@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {}
DubboConfigConfigurationRegistrar
public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// initialize dubbo beans
DubboSpringInitializer.initialize(registry);
}
}
DubboSpringInitializer
public static void initialize(BeanDefinitionRegistry registry) {
// ...
// init dubbo context
initContext(context, registry, beanFactory);
}
private static void initContext(DubboSpringInitContext context, BeanDefinitionRegistry registry,
ConfigurableListableBeanFactory beanFactory) {
// ...
// register common beans
DubboBeanUtils.registerCommonBeans(registry);
}
DubboBeanUtils
static void registerCommonBeans(BeanDefinitionRegistry registry) {
// ...
// Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
ReferenceAnnotationBeanPostProcessor.class);
// ...
}
2、bean处理器
所谓bean的后置处理器,其实就是在bean完成初始化之后,就会调用这个方法,给你所有的bean,然后你就可以对这个bean为所欲为了
bean处理器有很多,有前置处理器、后置处理器、bean工厂处理器
2-1、前、后置处理器
只需要实现BeanPostProcessor 接口,重写里面的前置、后置处理器就好了,系统会把每个bean作为参数去调用这个方法
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
2-2、bean工厂处理器
上面的前后置处理器,是系统拿到bean去调用这个方法,bean工厂处理器直接把bean工厂给你
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
3、循环所有的bean,找到使用注解的bean生成代理对象
ReferenceAnnotationBeanPostProcessor实现了BeanFactoryPostProcessor,重写了postProcessBeanFactory,在这个方法里面对使用了注解的bean进行代理
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 遍历所有的bean
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
Class<?> beanType;
// 判断是不是工厂bean,显然我们不是
if (beanFactory.isFactoryBean(beanName)) {
// ...
} else {
// 走这个、拿到class
beanType = beanFactory.getType(beanName);
}
if (beanType != null) {
// 找到需要被代理的 metadata
AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
try {
// 进行代理生成
prepareInjection(metadata);
} catch (BeansException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException("Prepare dubbo reference injection element failed", e);
}
}
}
}
4、找到合适的bean
匹配逻辑,其实就是拿每一个Class 上面的注解,看看是否和DubboReference相关注解匹配,下面代码给出大概步骤,忽略一些判断逻辑
setp 1
protected AnnotatedInjectionMetadata findInjectionMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
// ...
try {
// 走这里构建
metadata = buildAnnotatedMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
} catch (NoClassDefFoundError err) {
throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() +
"] for annotation metadata: could not find class that it depends on", err);
}
// ...
return metadata;
}
setp 2
private AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {
// 这个方法就会找到合适匹配的bean
Collection<AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);
Collection<AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);
return new AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);
}
setp 3
private List<AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement> findFieldAnnotationMetadata(final Class<?> beanClass) {
final List<AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement> elements = new LinkedList<>();
ReflectionUtils.doWithFields(beanClass, field -> {
for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
AnnotationAttributes attributes = AnnotationUtils.getAnnotationAttributes(field, annotationType, getEnvironment(), true, true);
if (attributes != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "@" + annotationType.getName() + " is not supported on static fields: " + field);
}
return;
}
elements.add(new AnnotatedFieldElement(field, attributes));
}
}
});
return elements;
}
getAnnotationTypes 就是在初始化的时候Set进去的
public ReferenceAnnotationBeanPostProcessor() {
super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class);
}
public AbstractAnnotationBeanPostProcessor(Class<? extends Annotation>... annotationTypes) {
Assert.notEmpty(annotationTypes, "The argument of annotations' types must not empty");
this.annotationTypes = annotationTypes;
}
5、注册 ReferenceBean类型的 beanDefinition
让我们再回到 ReferenceAnnotationBeanPostProcessor#postProcessBeanFactory
在这个方法里面循环每一个bean看它是否用到了 DubboReference 相关注解,如果有就进行代理对象
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
// ...
if (beanType != null) {
// 找到满足代理的bean,上一节已经讲了
AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
try {
// 进行代理
prepareInjection(metadata);
}
}
// ...
}
}
protected void prepareInjection(AnnotatedInjectionMetadata metadata) throws BeansException {
try {
//find and register bean definition for @DubboReference/@Reference
for (AnnotatedFieldElement fieldElement : metadata.getFieldElements()) {
if (fieldElement.injectedObject != null) {
continue;
}
Class<?> injectedType = fieldElement.field.getType();
AnnotationAttributes attributes = fieldElement.attributes;
// 注册代理bean
String referenceBeanName = registerReferenceBean(fieldElement.getPropertyName(), injectedType, attributes, fieldElement.field);
//associate fieldElement and reference bean
fieldElement.injectedObject = referenceBeanName;
injectedFieldReferenceBeanCache.put(fieldElement, referenceBeanName);
}
// ...
} catch (ClassNotFoundException e) {
throw new BeanCreationException("prepare reference annotation failed", e);
}
}
registerReferenceBean 方法很长,前面有一系列的校验和缓存处理,这里为了简便,只给出后面注册 beanDefinition 部分
public String registerReferenceBean(String propertyName, Class<?> injectedType, Map<String, Object> attributes, Member member) throws BeansException {
// ... 省略一大段校验缓存逻辑
// Register the reference bean definition to the beanFactory
RootBeanDefinition beanDefinition = new RootBeanDefinition();
// 看看看看,找到了,注册的这个 beanDefinition ,是 ReferenceBean.class
beanDefinition.setBeanClassName(ReferenceBean.class.getName());
// ... 省略赋值的逻辑
// 注册BeanDefinition, 被注册的 BeanDefinition,会生成一个对象
beanDefinitionRegistry.registerBeanDefinition(referenceBeanName, beanDefinition);
logger.info("Register dubbo reference bean: " + referenceBeanName + " = " + referenceKey + " at " + member);
return referenceBeanName;
}
6、生成代理对象 ReferenceBean
ReferenceBean 是一个FactoryBean,所以在需要这个bean的时候会调用getObject 获取bean
ReferenceBean<T> implements FactoryBean<T>,ApplicationContextAware, BeanClassLoaderAware, BeanNameAware, InitializingBean, DisposableBean
@Override
public T getObject() {
if (lazyProxy == null) {
createLazyProxy();
}
return (T) lazyProxy;
}
private void createLazyProxy() {
// ....
// 这里默认走的就是Javassist代理
if (StringUtils.isEmpty(this.proxy) || CommonConstants.DEFAULT_PROXY.equalsIgnoreCase(this.proxy)) {
generateFromJavassistFirst(interfaces);
}
if (this.lazyProxy == null) {
generateFromJdk(interfaces);
}
}
好啦,到这里代理对象就生成完毕了,这里看到它在代理对象里面注册了一个 LazyTargetInvocationHandler,它本质上是一个 InvocationHandler,所以当执行这个代理对象的时候就会执行org.apache.LazyTargetInvocationHandler#invoke
这就行下一期要讲的,运行原理
private void generateFromJavassistFirst(List<Class<?>> interfaces) {
try {
this.lazyProxy = Proxy.getProxy(interfaces.toArray(new Class[0])).newInstance(new LazyTargetInvocationHandler(new DubboReferenceLazyInitTargetSource()));
} catch (Throwable fromJavassist) {
// ...
}
}
二、@DubboService 注解解析
相较于@DubboReference,@DubboService的解析要复杂不少,先是扫描到带有注解的实体,生成 ServiceBean,再基于ServiceBean生成CallbackRegistrationInvoker对象
1、入口
@EnableDubbo > @DubboComponentScan > DubboComponentScanRegistrar.class
DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar
,重写了registerBeanDefinitions,这个方法里面就注入了Service处理器,通过扫描包下面使用相关注解的bean
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// initialize dubbo beans
DubboSpringInitializer.initialize(registry);
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
// 注册Service处理器
registerServiceAnnotationPostProcessor(packagesToScan, registry);
}
2、bean 处理器
通过扫描指定包下的bean来筛选是否满足生成 ServiceBean
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor#postProcessBeanDefinitionRegistry
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.registry = registry;
scanServiceBeans(resolvedPackagesToScan, registry);
}
scanServiceBeans
看看这里把 serviceAnnotationTypes
装进去了,下面判断的时候会用到
private void scanServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
// 循环每个包
for (String packageToScan : packagesToScan) {
DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
// 🌈🌈🌈🌈构建需要包含哪些bean, serviceAnnotationTypes 就是上面定义的注解
for (Class<? extends Annotation> annotationType : serviceAnnotationTypes) {
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
}
// 扫描每个包
scanner.scan(packageToScan);
// 找到合适的 BeanDefinition
Set<BeanDefinitionHolder> beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
// 循环每一个合适的 BeanDefinition
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
// 生成 ServiceBean
processScannedBeanDefinition(beanDefinitionHolder);
servicePackagesHolder.addScannedClass(beanDefinitionHolder.getBeanDefinition().getBeanClassName());
}
servicePackagesHolder.addScannedPackage(packageToScan);
}
}
serviceAnnotationTypes
private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
// @since 2.7.7 Add the @DubboService , the issue : https://github.com/apache/dubbo/issues/6007
DubboService.class,
// @since 2.7.0 the substitute @com.alibaba.dubbo.config.annotation.Service
Service.class,
// @since 2.7.3 Add the compatibility for legacy Dubbo's @Service , the issue : https://github.com/apache/dubbo/issues/4330
com.alibaba.dubbo.config.annotation.Service.class
);
3、找到合适的 BeanDefinition
这里寻找的过程有一点绕,还是和之前一起,给出每个关键节点的关键代码
本质上就是扫描包下面的BeanDefinition看看是否有包含 @DubboService相关注解
findServiceBeanDefinitionHolders
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor#findServiceBeanDefinitionHolders
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;
}
findCandidateComponents
org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner#findCandidateComponents
@Override
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
Set<BeanDefinition> beanDefinitions = beanDefinitionMap.get(basePackage);
// if beanDefinitions size is null => scan
if (Objects.isNull(beanDefinitions)) {
beanDefinitions = super.findCandidateComponents(basePackage);
beanDefinitionMap.put(basePackage, beanDefinitions);
}
return beanDefinitions;
}
scanCandidateComponents
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet();
// ...
MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
if (this.isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
// 判断当前bean是不是满足
if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
if (debugEnabled) {
this.logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
} else if (debugEnabled) {
this.logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
// ...
return candidates;
}
isCandidateComponent
includeFilters
数据就是在scanServiceBeans 里面设置进去的
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isCandidateComponent(org.springframework.core.type.classreading.MetadataReader)
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
Iterator var2 = this.excludeFilters.iterator();
TypeFilter tf;
do {
if (!var2.hasNext()) {
var2 = this.includeFilters.iterator();
do {
if (!var2.hasNext()) {
return false;
}
tf = (TypeFilter)var2.next();
} while(!tf.match(metadataReader, this.getMetadataReaderFactory()));
return this.isConditionMatch(metadataReader);
}
tf = (TypeFilter)var2.next();
} while(!tf.match(metadataReader, this.getMetadataReaderFactory()));
return false;
}
4、生成ServiceBean
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor#processScannedBeanDefinition
private void processScannedBeanDefinition(BeanDefinitionHolder beanDefinitionHolder) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Annotation service = findServiceAnnotation(beanClass);
// The attributes of @Service annotation
Map<String, Object> serviceAnnotationAttributes = AnnotationUtils.getAttributes(service, true);
String serviceInterface = resolveInterfaceName(serviceAnnotationAttributes, beanClass);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
// ServiceBean Bean name
String beanName = generateServiceBeanName(serviceAnnotationAttributes, serviceInterface);
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(serviceAnnotationAttributes, serviceInterface, annotatedServiceBeanName);
registerServiceBeanDefinition(beanName, serviceBeanDefinition, serviceInterface);
}
生成beanName
private String generateServiceBeanName(Map<String, Object> serviceAnnotationAttributes, String serviceInterface) {
ServiceBeanNameBuilder builder = create(serviceInterface, environment)
.group((String) serviceAnnotationAttributes.get("group"))
.version((String) serviceAnnotationAttributes.get("version"));
return builder.build();
}
构建bean参数
定义 BeanDefinition 的class,并且解析注解上的参数,放入BeanDefinition
private AbstractBeanDefinition buildServiceBeanDefinition(Map<String, Object> serviceAnnotationAttributes,
String serviceInterface,
String refServiceBeanName) {
// 设置class
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
String[] ignoreAttributeNames = ObjectUtils.of("provider", "monitor", "application", "module", "registry", "protocol",
"methods", "interfaceName", "parameters", "executor");
propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotationAttributes, environment, ignoreAttributeNames));
addPropertyReference(builder, "ref", refServiceBeanName);
// Set interface
builder.addPropertyValue("interface", serviceInterface);
// ... 设置各种参数
return builder.getBeanDefinition();
}
注册到 BeanDefinitionRegistry
private void registerServiceBeanDefinition(String serviceBeanName, AbstractBeanDefinition serviceBeanDefinition, String serviceInterface) {
// check service bean
// ...
registry.registerBeanDefinition(serviceBeanName, serviceBeanDefinition);
// ...
}
5、ServiceBean
一般生成代理对象,都会有一个 invoker方法,但ServiceBean没有,这是因为ServiceBean 只是存储DubboService的相关信息,后面还会生成一个真正invoker。
先来看一下ServiceBean的继承关系
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean,
ApplicationContextAware, BeanNameAware, ApplicationEventPublisherAware {}
真正的invoker是在 ServiceConfig中生成的
ServiceBean 重写了 afterPropertiesSet ,把自己注册到了moduleConfigManager(这个后面会看到)
@Override
public void afterPropertiesSet() throws Exception {
if (StringUtils.isEmpty(getPath())) {
if (StringUtils.isNotEmpty(getInterface())) {
setPath(getInterface());
}
}
//register service bean
ModuleModel moduleModel = DubboBeanUtils.getModuleModel(applicationContext);
moduleModel.getConfigManager().addService(this);
moduleModel.getDeployer().setPending();
}
6、invoker生成
Dubbo注册了一个事件监听器,这个事件监听器会做很多初始化的工作,就会到生成Invoker的地方,这里的调用链路太长了,给一个Debug的图
最终会到当前类的org.apache.dubbo.config.ServiceConfig#doExportUrl方法
private void doExportUrl(URL url, boolean withMetaData, RegisterTypeEnum registerType) {
if (!url.getParameter(REGISTER_KEY, true)) {
registerType = RegisterTypeEnum.MANUAL_REGISTER;
}
if (registerType == RegisterTypeEnum.NEVER_REGISTER ||
registerType == RegisterTypeEnum.MANUAL_REGISTER ||
registerType == RegisterTypeEnum.AUTO_REGISTER_BY_DEPLOYER) {
url = url.addParameter(REGISTER_KEY, false);
}
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
if (withMetaData) {
invoker = new DelegateProviderMetaDataInvoker(invoker, this);
}
Exporter<?> exporter = protocolSPI.export(invoker);
exporters.computeIfAbsent(registerType, k -> new CopyOnWriteArrayList<>()).add(exporter);
}
interfaceClass 取的是刚刚解析ServiceBean来的,也就是使用DubboService注解的类,invoker 返回的是Java生成的代理对象,Dubbo会再把它包装一层,所谓的包装就是用 Filter去包它,一层层的。最终生成 CallbackRegistrationInvoker。
withMetaData: 每一个使用DubboService注解的对象都会生成两个代理对象,一个正常的代理对象,用来执行服务,一个 MetaData 类型的代理对象,用来维护基础数据
后续Netty收到请求,就会转而找到对应的 Invoker。