栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

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

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

前言:

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方法,在执行前执行的方法可以为前置通知,后执行则反之

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

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

    /// 
    /// 接口方法本身可以作为环绕通知 AroundAdvice,其中的Invocation 无疑就是JavaAOP中类似JoinPoint的作用
    /// 
    /// 
    public void Intercept(IInvocation invocation)
    {
            BeforeAdvice();
            invocation.Proceed();
            AfterAdvice();
    }
}
三.将切面注册进容器并配置
static void Main(string[] args)
{
 ContainerBuilder Builder = new ContainerBuilder();
 //注册切面
 Builder.RegisterType();
 //给注册的接口实现类配置切面,
 Builder.RegisterType().As().InterceptedBy(typeof(DogAspect)).EnableInterfaceInterceptors();
                                    //开启接口AOP
 IContainer container = Builder.Build();
 using(var scope = container.BeginLifetimeScope())
 {
     DogeAction doge = scope.Resolve();
     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();
    Builder.RegisterType().InterceptedBy(typeof(DogAspect)).EnableClassInterceptors();
                                   //只需要在这改一下
    IContainer container = Builder.Build();
    using(var scope = container.BeginLifetimeScope())
    {
        Doge doge = scope.Resolve();
        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();
     Builder.RegisterType().As().InterceptedBy(typeof(DogAspect)).EnableInterfaceInterceptors();

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


 }

结果:

before doge Action:EAT
Doge is Eating shit
after doge Action:EAT
Doge is Peeing
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/984973.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号