AutoFac的AOP的实现以及和SpringAOP方式的对比

本文详细介绍了AutoFac和Spring的AOP动态代理机制,包括基于接口的JDK动态代理和CGLib子类代理。通过实例展示了如何在AutoFac中注册切面并配置拦截器,以及如何控制代理的生效范围。同时,讨论了切入点(PointCut)的处理,指出在AutoFac中如何手动指定织入方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

AutoFac的AOP和Spring的AOP一样都是基于动态代理的设计模式(废话)

其中Spring的动态代理有两种方式

Dynamic Proxy
JDK在1.5版本提供的原生动态代理,主要为InvocationHandler接口(切面)及产生代理类的Proxy类(代理对象PS:不是被代理对象) ,其本质是基于接口的生产方式,如果被代理类没有实现任何接口则无法使用
CGLib 则是通过子类生产代理对象,如果被代理类被final修饰,则无法产生代理

现在的Spring已经支持这两种方式并可以在其中切换了

当然 AutoFac的动态代理也支持上述的两种方式,但也稍微有些不同

1.AutoFac的接口动态代理

一.首先需要一个接口及实现类(这个类就是被代理对象,一般称为Target)

 public interface DogeAction
 {
     string EatSomething(string food);
 }

 public class Doge : DogeAction
 {
     public string EatSomething(string food)
     {
         Console.WriteLine("Doge is Eating "+food);
         return food;
     }
 }

二.其次需要一个切面,我们可以在里面定义各种增强的方法(Advice)

在Spring中的步骤一般是这样的
定义一个切面打上@Aspect
定义你想要织入的方法(Advice),打上@Before,@After,@Around然后指定PointCut切点
即可
在AutoFac中只要实现IInterceptor即可,需要在实现的 Intercept方法中执行invocation参数(其实就是代理对象)的Proceed方法,在执行前执行的方法可以为前置通知,后执行则反之

/// <summary>
/// 这个类为AOP的切面类,在这里面可以在代理对象(target)方法执行的前后添加ADVICE METHOD(增强方法)
/// </summary>
public class DogAspect : IInterceptor
{
    /// <summary>
    /// 前置通知
    /// </summary>
    public void BeforeAdvice()
    {
        Console.WriteLine("before doge Action");
    }

    /// <summary>
    /// 后置通知
    /// </summary>
    public void AfterAdvice()
    {
        Console.WriteLine("after doge Action");
    }

    /// <summary>
    /// 接口方法本身可以作为环绕通知 AroundAdvice,其中的Invocation 无疑就是JavaAOP中类似JoinPoint的作用
    /// </summary>
    /// <param name="invocation"></param>
    public void Intercept(IInvocation invocation)
    {
            BeforeAdvice();
            invocation.Proceed();
            AfterAdvice();
    }
}

三.将切面注册进容器并配置

static void Main(string[] args)
{
 ContainerBuilder Builder = new ContainerBuilder();
 //注册切面
 Builder.RegisterType<DogAspect>();
 //给注册的接口实现类配置切面,
 Builder.RegisterType<Doge>().As<DogeAction>().InterceptedBy(typeof(DogAspect)).EnableInterfaceInterceptors();
                                    //开启接口AOP
 IContainer container = Builder.Build();
 using(var scope = container.BeginLifetimeScope())
 {
     DogeAction doge = scope.Resolve<DogeAction>();
     doge.EatSomething("shit");   
 }
 }

结果:

before doge Action
Doge is Eating shit
after doge Action

2.AutoFac的子类动态代理

要使用子类代理,
首先,你的目标类target不能实现任何接口

public class Doge 
{
    public string EatSomething(string food)
    {
        Console.WriteLine("Doge is Eating "+food);
        return food;
    }
}

然后再该一下注册的代理生成方式即可,非常的简单

static void Main(string[] args)
{
    ContainerBuilder Builder = new ContainerBuilder();
    Builder.RegisterType<DogAspect>();
    Builder.RegisterType<Doge>().InterceptedBy(typeof(DogAspect)).EnableClassInterceptors();
                                   //只需要在这改一下
    IContainer container = Builder.Build();
    using(var scope = container.BeginLifetimeScope())
    {
        Doge doge = scope.Resolve<Doge>();
        doge.EatSomething("shit");
       
    }


}

结果:

before doge Action
Doge is Eating shit
after doge Action

3.二者对于切入点(PointCut)的处理

在Spring的AOP中,明确有着切入点的概念,

使用Execute表达式可以很自由的方法或缩小切入点的范围
在AOP的概念中,Aspect是我们想要织入的功能,
它必须要有一个切入的地方叫切入点(PontCut)
切点可大可小
大到一整个类,小到方法中的一个参数(Execute表达式都能够表示)
像上例中,织入的方法会在整个被代理类的所有实现方法上生效

public interface DogeAction
{
    string EatSomething(string food);
    void DogePee();
    
}

public class Doge:DogeAction
{
    public void DogePee()
    {
        Console.WriteLine("Doge is Peeing");
    }

    public string EatSomething(string food)
    {
        Console.WriteLine("Doge is Eating "+food);
        return food;
    }
}

如果只需要在特定的方法上(指定方法,或者去匹配方法),这需要手动完成,也就是去切面的Intercept里判断

public void Intercept(IInvocation invocation)
{
    //判断需要被织入的方法
    if(invocation.Method.Name== "EatSomething")
    {
        BeforeAdvice();
        invocation.Proceed();
        AfterAdvice();
    }
    else
    {   //不需要织入的方法则直接让它正常执行
        invocation.Proceed();
    }
    
}

测试:

 static void Main(string[] args)
 {
     ContainerBuilder Builder = new ContainerBuilder();
     Builder.RegisterType<DogAspect>();
     Builder.RegisterType<Doge>().As<DogeAction>().InterceptedBy(typeof(DogAspect)).EnableInterfaceInterceptors();

     IContainer container = Builder.Build();
     using(var scope = container.BeginLifetimeScope())
     {
         DogeAction doge = scope.Resolve<DogeAction>();
         doge.EatSomething("shit");
         doge.DogePee();
     }


 }

结果:

before doge Action:EAT
Doge is Eating shit
after doge Action:EAT
Doge is Peeing
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗马苏丹默罕默德

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值