Autofac DynamicProxy缓存拦截器同类内部方法调用不生效问题求助
问题根源
你当前使用的是接口拦截模式:Autofac DynamicProxy 会生成实现了IClassRepository接口的代理类,代理类内部持有真实ClassRepository实例,外部调用接口方法时会先走代理的拦截逻辑,因此调用Method2时拦截生效。但同一个类内部Method2调用Method1是真实实例直接调用自身方法,没有走代理层,因此拦截器不会触发。
解决方案
方案1:改用类代理(虚方法拦截,改动最小)
这种方式会让代理类继承自你的Repository实现类,重写带拦截逻辑的虚方法,内部调用也会走代理重写后的逻辑。
- 将Repository内需要被拦截的方法改为
virtual修饰:
public class ClassRepository : IClassRepository { [Cache] // 加virtual修饰 public virtual async Task<List<string>> Method1() { //Do some thing } [Cache] // 加virtual修饰 public virtual async Task<List<string>> Method2() { var methodCall = await Method1(); } }
- 修改Autofac注册代码,将
EnableInterfaceInterceptors改为EnableClassInterceptors:
public class RepositoryModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<CacheInterceptor>(); var flightDataAccess = Assembly.Load("DataAccess"); builder.RegisterAssemblyTypes(flightDataAccess) .Where(x => x.Name.EndsWith("Repository")) .AsImplementedInterfaces() .InstancePerLifetimeScope() .InterceptedBy(typeof(CacheInterceptor)) // 替换原来的EnableInterfaceInterceptors .EnableClassInterceptors(); } }
方案2:内部注入自身接口实例,不直接用this调用
如果不想改方法为虚方法,可以在类内部注入代理后的接口实例,内部调用时用注入的实例调用:
public class ClassRepository : IClassRepository { private readonly IClassRepository _proxySelf; // 注入自身的接口实例,Autofac会自动注入代理后的对象 public ClassRepository(IClassRepository proxySelf) { _proxySelf = proxySelf; } [Cache] public async Task<List<string>> Method1() { //Do some thing } [Cache] public async Task<List<string>> Method2() { // 调用代理实例的方法,触发拦截 var methodCall = await _proxySelf.Method1(); } }
注意:需要确保Repository的生命周期不是单例,避免循环依赖问题,你当前用的InstancePerLifetimeScope完全支持这种写法。
额外优化建议
你当前拦截器中ProcessInterceptAsync(invocation).Wait()是同步阻塞异步方法,高并发场景下容易出现死锁,建议改用Castle官方的AsyncInterceptor基类实现异步拦截,避免阻塞问题。
内容的提问来源于stack exchange,提问作者Amirhossein Yari
相关产品推荐
相关产品推荐

