避免循环依赖注入
Avoid Circular Dependency injection
在我的 Angular 应用程序中,我正在实施 2 项服务:
- 身份验证服务
- 空闲服务
这两个服务相互依赖:
- 当我注销时,我必须停止监视用户闲置(通过调用
IdleService
中的方法)
- 当用户超时时,我必须从
AuthenticationService
调用 logout
方法来注销用户。
这种方法会导致循环依赖问题。您知道如何避免它或如何通过更好的方法改变我的实际方法吗?
您可以在 IdleService
中创建一个 observable 或一个主题,如果时间用完,returns 一个断开消息。这样,只有 AuthenticationService
导入 IdleService
。例如:
import { IdleService } from './services/idle.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthenticationService {
disconnect: Obervable<boolean>;
constructor(private idleService: IdleService) {
this.disconnect = this.idleService.disconnectObservable;
this.disconnect.subscribe(res => {
if (res === true) {
this.logout();
}
});
}
logout() {
//some code here
}
}
在IdleService
中:
import { Observable } from 'rxjs/Observable';
@Injectable()
export class IdleService {
public disconnectObservable: Observable<boolean>;
constructor() {
this.disconnectObservable = new Observable(observer => {
// insert your logic here
setTimeout(() => {
observer.next('true');
}, 1000);
setTimeout(() => {
observer.complete();
}, 3000);
});
}
}
书中Dependency Injection in .NET 2nd edition (§6.3), Mark Seemann and I describe that Dependency cycles are often caused by Single Responsibility Principle违规。我的印象是,在您的具体情况下也是如此。当 class 有许多不是很内聚的方法时,通常会违反 SRP。
解决方案是将两个 classes AuthenticationService
和 IdleService
(或者甚至两者)中的任何一个拆分成更小的 classes。
我会说身份验证服务负责保存、管理和公开用户身份验证的状态。通过这个我是说授权服务根本不应该关心用户空闲。这是空闲服务的责任。
所以我会在 auth 服务中创建一个 BehaviorSubject 来广播用户身份验证的状态。空闲服务可以使用主题来确定空闲计时器何时需要start/stop。
export class AuthService {
user: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
logIn(){
// logic to log user in
this.user.next(true);
}
logOut(){
// logic to log user out
this.user.next(false);
}
}
现在idle服务可以注入auth服务并决定如何处理idle定时器
export class IdleService {
constructor(private authService: AuthService){
this.authService.user.subscribe(res => {
// watch user authentication state and determine how to handle idle timer
});
}
idleOut(){
this.authService.logOut();
}
}
为此,您必须在应用程序加载时注入 IdleService(例如在 app.component 中,以便运行 IdleService 构造函数。我不确定这是否是最优雅的解决方案,但是这是首先想到的。这是一个非常基本的 stackblitz 演示这个概念。
在我的 Angular 应用程序中,我正在实施 2 项服务:
- 身份验证服务
- 空闲服务
这两个服务相互依赖:
- 当我注销时,我必须停止监视用户闲置(通过调用
IdleService
中的方法) - 当用户超时时,我必须从
AuthenticationService
调用logout
方法来注销用户。
这种方法会导致循环依赖问题。您知道如何避免它或如何通过更好的方法改变我的实际方法吗?
您可以在 IdleService
中创建一个 observable 或一个主题,如果时间用完,returns 一个断开消息。这样,只有 AuthenticationService
导入 IdleService
。例如:
import { IdleService } from './services/idle.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthenticationService {
disconnect: Obervable<boolean>;
constructor(private idleService: IdleService) {
this.disconnect = this.idleService.disconnectObservable;
this.disconnect.subscribe(res => {
if (res === true) {
this.logout();
}
});
}
logout() {
//some code here
}
}
在IdleService
中:
import { Observable } from 'rxjs/Observable';
@Injectable()
export class IdleService {
public disconnectObservable: Observable<boolean>;
constructor() {
this.disconnectObservable = new Observable(observer => {
// insert your logic here
setTimeout(() => {
observer.next('true');
}, 1000);
setTimeout(() => {
observer.complete();
}, 3000);
});
}
}
书中Dependency Injection in .NET 2nd edition (§6.3), Mark Seemann and I describe that Dependency cycles are often caused by Single Responsibility Principle违规。我的印象是,在您的具体情况下也是如此。当 class 有许多不是很内聚的方法时,通常会违反 SRP。
解决方案是将两个 classes AuthenticationService
和 IdleService
(或者甚至两者)中的任何一个拆分成更小的 classes。
我会说身份验证服务负责保存、管理和公开用户身份验证的状态。通过这个我是说授权服务根本不应该关心用户空闲。这是空闲服务的责任。
所以我会在 auth 服务中创建一个 BehaviorSubject 来广播用户身份验证的状态。空闲服务可以使用主题来确定空闲计时器何时需要start/stop。
export class AuthService {
user: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
logIn(){
// logic to log user in
this.user.next(true);
}
logOut(){
// logic to log user out
this.user.next(false);
}
}
现在idle服务可以注入auth服务并决定如何处理idle定时器
export class IdleService {
constructor(private authService: AuthService){
this.authService.user.subscribe(res => {
// watch user authentication state and determine how to handle idle timer
});
}
idleOut(){
this.authService.logOut();
}
}
为此,您必须在应用程序加载时注入 IdleService(例如在 app.component 中,以便运行 IdleService 构造函数。我不确定这是否是最优雅的解决方案,但是这是首先想到的。这是一个非常基本的 stackblitz 演示这个概念。