abp vnext blog模块用户信息同步 源码解析
先看一下Volo.Blogging.Domain引用的关于用户的项目只有Volo.Abp.Users.Domain,再看BlogUser定义:
public class BlogUser : AggregateRoot<Guid>, IUser, IUpdateUserData
{
public virtual Guid? TenantId { get; protected set; }
...
先记下这个点:IUpdateUserData ,查看源码
public interface IUpdateUserData
{
bool Update([NotNull] IUserData user);
}
查看文件BlogUserLookupService
public class BlogUserLookupService : UserLookupService<BlogUser, IBlogUserRepository>, IBlogUserLookupService
{
public BlogUserLookupService(
IBlogUserRepository userRepository,
IUnitOfWorkManager unitOfWorkManager)
: base(
userRepository,
unitOfWorkManager)
{
}
protected override BlogUser CreateUser(IUserData externalUser)
{
return new BlogUser(externalUser);
}
}
啥也没干就继承了泛型类UserLookupService,重点看UserLookupService类,这个类有三个主要方法:FindByIdAsync,FindByUserNameAsync,SearchAsync,主要看下FindByIdAsync方法:
public async Task<TUser> FindByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
// _userRepository继承类的泛型,对应IBlogUserRepository,localUser 指blog模块中的用户信息
var localUser = await _userRepository.FindAsync(id, cancellationToken: cancellationToken);
// IExternalUserLookupServiceProvider搜索整个源码文件只用IdentityUserRepositoryExternalUserLookupServiceProvider和HttpClientExternalUserLookupServiceProvider实现这个接口,
// 一般情况下这个应该不为空,如果ExternalUserLookupServiceProvider为空,即返回
if (ExternalUserLookupServiceProvider == null)
{
return localUser;
}
// SkipExternalLookupIfLocalUserExists在UserLookupService默认为true,其他地方未修改
// 本地bloguser不存在且SkipExternalLookupIfLocalUserExists返回bloguser
if (SkipExternalLookupIfLocalUserExists && localUser != null)
{
return localUser;
}
IUserData externalUser;
try
{
// 使用ExternalUserLookupServiceProvider方法获取User数据,这个ExternalUserLookupServiceProvider是IdentityUserRepositoryExternalUserLookupServiceProvider
//
externalUser = await ExternalUserLookupServiceProvider.FindByIdAsync(id, cancellationToken);
// IdentityUserRepositoryExternalUserLookupServiceProvider也不存在User信息
if (externalUser == null)
{
// 删除bloguser
if (localUser != null)
{
//TODO: Instead of deleting, should be make it inactive or something like that?
await WithNewUowAsync(() => _userRepository.DeleteAsync(localUser, cancellationToken: cancellationToken));
}
return null;
}
}
catch (Exception ex)
{
Logger.LogException(ex);
return localUser;
}
// externalUser 不为空。bloguser为空,插入bloguser库
if (localUser == null)
{
await WithNewUowAsync(() => _userRepository.InsertAsync(CreateUser(externalUser), cancellationToken: cancellationToken));
return await _userRepository.FindAsync(id, cancellationToken: cancellationToken);
}
// bloguser不为空,实现IUpdateUserData接口且存在更新内容,则更新bloguser数据
if (localUser is IUpdateUserData && ((IUpdateUserData)localUser).Update(externalUser))
{
await WithNewUowAsync(() => _userRepository.UpdateAsync(localUser, cancellationToken: cancellationToken));
}
else
{
return localUser;
}
return await _userRepository.FindAsync(id, cancellationToken: cancellationToken);
}
到此位置,当在blog模块中调用UserLookupService时,获取到的用户信息是和Identity模块中用户信息是同步的,Identity有blog没的添加一个,Identity没blog有删除一个,Identity和blog不一样的更新到blog一个,然后再看看BlogUserSynchronizer类,这个类订阅一个事件:
public async Task HandleEventAsync(EntityUpdatedEto<UserEto> eventData)
{
// 本地库bloguser查找
var user = await UserRepository.FindAsync(eventData.Entity.Id);
if (user == null)
{
// 本地查不到,看看Identity里有没,
user = await UserLookupService.FindByIdAsync(eventData.Entity.Id);
if (user == null)
{
return;
}
}
// 不管哪有,最后更新到bloguser库里
if (user.Update(eventData.Entity))
{
await UserRepository.UpdateAsync(user);
}
}
至此,完成所有同步工作。
貌似还有点糊涂,欢迎大家指导!