TypeScript中使用Tsyringe实现接口多实例按需注入的问题
解决Tsyringe中基于构建参数的接口依赖注入问题
你的需求完全可以在TypeScript中实现,核心思路是通过构建时条件导入+实现类自注册,让选中的代理实现自动完成Tsyringe容器的令牌注册,同时利用构建工具的Tree-Shake特性剔除未被选中的实现代码。以下是具体方案:
步骤1:给每个代理实现添加自注册逻辑
在每个代理实现类文件末尾添加容器注册代码,确保文件被导入时自动完成令牌绑定:
// KeyCloak/KeycloakAuthProxyImpl.ts import { container, injectable } from 'tsyringe'; import { AuthProxy } from '../AuthProxy'; @injectable() export class KeycloakAuthProxyImpl implements AuthProxy { login(username: string, password: string): Promise<any> { // Keycloak登录逻辑实现 } } // 自注册逻辑:文件被导入时自动执行 container.register('AuthProxy', { useClass: KeycloakAuthProxyImpl });
// AuthZero/AuthZeroAuthProxyImpl.ts import { container, injectable } from 'tsyringe'; import { AuthProxy } from '../AuthProxy'; @injectable() export class AuthZeroAuthProxyImpl implements AuthProxy { login(username: string, password: string): Promise<any> { // AuthZero登录逻辑实现 } } // 自注册逻辑:文件被导入时自动执行 container.register('AuthProxy', { useClass: AuthZeroAuthProxyImpl });
步骤2:创建动态导入的注册入口
新建一个proxy-registry.ts文件,根据构建参数动态导入对应的实现类:
// proxy-registry.ts // 通过构建时注入的环境变量决定加载哪个实现 const proxyType = process.env.PROXY_TYPE || 'keycloak'; // 动态导入触发自注册 if (proxyType === 'keycloak') { import('./KeyCloak/KeycloakAuthProxyImpl'); } else if (proxyType === 'authzero') { import('./AuthZero/AuthZeroAuthProxyImpl'); }
步骤3:在Lambda Handler中初始化注册
在Lambda的入口文件中先导入注册入口,再使用依赖注入:
// handler.ts // 先执行代理注册逻辑 import './proxy-registry'; import { container } from 'tsyringe'; import { AuthProxy } from './AuthProxy'; export const handler = async (event: any) => { // 从容器中解析代理实例 const authProxy = container.resolve<AuthProxy>('AuthProxy'); const loginResult = await authProxy.login(event.username, event.password); return { statusCode: 200, body: JSON.stringify(loginResult) }; };
步骤4:配置构建脚本控制实现类打包
在package.json中添加构建脚本,通过构建工具(以ESBuild为例)传递参数注入环境变量,同时触发Tree-Shake剔除未选中的代码:
{ "scripts": { "build:keycloak": "esbuild handler.ts --bundle --platform=node --define:process.env.PROXY_TYPE=\"keycloak\" --outfile=dist/handler.js", "build:authzero": "esbuild handler.ts --bundle --platform=node --define:process.env.PROXY_TYPE=\"authzero\" --outfile=dist/handler.js" } }
执行npm run build:keycloak时,ESBuild会只打包Keycloak相关代码,且对应实现类的自注册逻辑会在运行时自动执行,容器就能正确解析AuthProxy令牌。
为什么之前的方案无效?
- 直接将注册逻辑放在实现类但未执行:因为未被选中的实现类文件被构建工具Tree-Shake剔除,代码从未被导入执行,注册逻辑自然不会触发。
@registry装饰器无效:Tsyringe的@registry需要在容器初始化时扫描到对应的元数据,若文件被剔除,装饰器的元数据也不会被处理。
内容的提问来源于stack exchange,提问作者sebin vincent
相关产品推荐
相关产品推荐

