AOP原理解析及Castle、Autofac、Unity框架使用

转自:https://www.cnblogs.com/neverc/p/5241466.html

AOP介绍

面向切面编程(Aspect Oriented Programming,英文缩写为AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP是OOP的延续,是软件开发中的一个热点.

常用于:

Authentication 

Caching

Lazy loading

Transactions

 

AOP基本原理

普通类

1
2
3
4
5
6
7
8
9
class Person : MarshalByRefObject
{
    public string Say()
    {
        const string str = "Person's say is called";
        Console.WriteLine(str);
        return str;
    }
}

代理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Proxy<T> : RealProxy where T : new()
{
    private object _obj;
    public Proxy(object obj)
        base(typeof(T))
    {
        _obj = obj;
    }
    public override IMessage Invoke(IMessage msg)
    {
        Console.WriteLine("{0}:Invoke前", DateTime.Now);
        var ret = ((IMethodCallMessage)msg).MethodBase.Invoke(_obj, null);
        Console.WriteLine("{0}:Invoke后", DateTime.Now);
        return new ReturnMessage(ret, null, 0, nullnull);
    }
}

执行

1
2
3
4
5
6
7
8
9
10
static void Main(string[] args)
{
    var per = new Proxy<Person>(new Person()).GetTransparentProxy() as Person;
    if (per != null)
    {
        var str = per.Say();
        Console.WriteLine("返回值:" + str);
    }
    Console.ReadKey();
}

 

AOP框架

AOP有动态代理和静态IL织入.

本节主要介绍动态代理方式,静态可参考PostSharp.

 

Castle Core

原理:本质是创建继承原来类的代理类.重写虚方法实现AOP功能.

 

只需引用:

Install-Package Castle.Core

(在Castle的2.5以上版本,已经将 Castle.DynamicProxy2.dll 里有内容,集成到 Castle.Core.dll 中。)

 

Simple Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class Person
{
    public virtual void SayHello()
    {
        Console.WriteLine("我是{0}方法""SayHello");
    }
    public virtual void SayName(string name)
    {
        Console.WriteLine("我是{0}方法,参数值:{1}""SayName", name);
    }
    public abstract void AbstactSayOther();
    public void SayOther()
    {
        Console.WriteLine("我是{0}方法""SayOther");
    }
}

 

interceptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SimpleInterceptor : StandardInterceptor
{
    protected override void PreProceed(IInvocation invocation)
    {
        Console.WriteLine("拦截器调用方法前,方法名是:{0}。", invocation.Method.Name);
    }
    protected override void PerformProceed(IInvocation invocation)
    {
        Console.WriteLine("拦截器开始调用方法,方法名是:{0}。", invocation.Method.Name);
        var attrs = invocation.MethodInvocationTarget.Attributes.HasFlag(MethodAttributes.Abstract);//过滤abstract方法
        if (!attrs)
        {
            base.PerformProceed(invocation);//此处会调用真正的方法 invocation.Proceed();
        }
    }
    protected override void PostProceed(IInvocation invocation)
    {
        Console.WriteLine("拦截器调用方法后,方法名是:{0}。", invocation.Method.Name);
    }
}

 

Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static void Main(string[] args)
{
    var generator = new ProxyGenerator();       //实例化【代理类生成器】 
    var interceptor = new SimpleInterceptor();  //实例化【拦截器】 
    //使用【代理类生成器】创建Person对象,而不是使用new关键字来实例化 
    var person = generator.CreateClassProxy<Person>(interceptor);
    Console.WriteLine("当前类型:{0},父类型:{1}", person.GetType(), person.GetType().BaseType);
    Console.WriteLine();
    person.SayHello();//拦截
    Console.WriteLine();
    person.SayName("Never、C");//拦截
    Console.WriteLine();
    person.SayOther();//普通方法,无法拦截    
    person.AbstactSayOther();//抽象方法,可以拦截    
    Console.ReadLine();
}

 

Castle Windsor

特性式AOP

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface IPerson
{
    void Say();
}
[Interceptor(typeof(LogInterceptor))]
public class Person : IPerson
{
    public void Say()
    {
        Console.WriteLine("Person's Say Method is called!");
    }
}

 

1
2
3
4
5
6
7
8
9
public class LogInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("{0}:拦截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
        invocation.Proceed();
        Console.WriteLine("{0}:拦截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
    using (var container = new WindsorContainer())
    {
        container.Register(Component.For<Person, IPerson>());
        container.Register(Component.For<LogInterceptor, IInterceptor>());
        var person = container.Resolve<IPerson>();
        person.Say();
    }
    Console.ReadKey();
}


非侵入式AOP

1
2
3
4
5
6
7
8
9
10
11
12
public interface IPerson
{
    void Say();
}
public class Person : IPerson
{
    public void Say()
    {
        Console.WriteLine("Person's Say Method is called!");
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
internal static class LogInterceptorRegistrar
{
    public static void Initialize(WindsorContainer container)
    {
        container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
    }
    private static void Kernel_ComponentRegistered(string key, IHandler handler)
    {
        handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(LogInterceptor)));
    }
}
public class LogInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("{0}:拦截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
        invocation.Proceed();
        Console.WriteLine("{0}:拦截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
static void Main(string[] args)
{
    using (var container = new WindsorContainer())
    {
        container.Register(Component.For<IInterceptor, LogInterceptor>());//先注入拦截器
        LogInterceptorRegistrar.Initialize(container);
        container.Register(Component.For<IPerson, Person>());
        var person = container.Resolve<IPerson>();
        person.Say();
    }
    Console.ReadKey();
}

 

Autofac

Install-Package Autofac.Aop

通过特性标签绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class LogInterceptor : IInterceptor
 {
     public void Intercept(IInvocation invocation)
     {
         Console.WriteLine("{0}:拦截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
         invocation.Proceed();
         Console.WriteLine("{0}:拦截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
     }
 }
 public interface IPerson
 {
     void Say();
 }
 [Intercept(typeof(LogInterceptor))]
 public class Person : IPerson
 {
     public void Say()
     {
         Console.WriteLine("Person's Say Method is called!");
     }
 }

 

启用拦截器执行

1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
    var builder = new ContainerBuilder();
    builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors();
    builder.RegisterType<LogInterceptor>();
    using (var container = builder.Build())
    {
        container.Resolve<IPerson>().Say();
    }
    Console.ReadLine();
}

 

或采用非侵入性方法(去掉class上的特性仍可以)

1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
    var builder = new ContainerBuilder();
    builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors().InterceptedBy(typeof(LogInterceptor));
    builder.RegisterType<LogInterceptor>();
    using (var container = builder.Build())
    {
        container.Resolve<IPerson>().Say();
    }
    Console.ReadLine();
}

  

 

Unity

Unity默认提供了三种拦截器:TransparentProxyInterceptor、InterfaceInterceptor、VirtualMethodInterceptor。

TransparentProxyInterceptor:代理实现基于.NET Remoting技术,它可拦截对象的所有函数。缺点是被拦截类型必须派生于MarshalByRefObject。

InterfaceInterceptor:只能对一个接口做拦截,好处时只要目标类型实现了指定接口就可以拦截。

VirtualMethodInterceptor:对virtual函数进行拦截。缺点是如果被拦截类型没有virtual函数则无法拦截,这个时候如果类型实现了某个特定接口可以改用

 

Install-Package Unity.Interception

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyHandler : ICallHandler
{
    public int Order { getset; }//这是ICallHandler的成员,表示执行顺序
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("方法执行前");
        //这之前插入方法执行前的处理
        var retvalue = getNext()(input, getNext);//在这里执行方法
        //这之后插入方法执行后的处理
        Console.WriteLine("方法执行后");
        return retvalue;
    }
}

 

1
2
3
4
5
6
7
public class MyHandlerAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new MyHandler();//返回MyHandler
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface IPerson
{
    void Say();
}
[MyHandler]
public class Person : IPerson
{
    public virtual void Say()
    {
        Console.WriteLine("Person's Say Method is called!");
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static void Main(string[] args)
{
    using (var container = new UnityContainer())
    {
        container.AddNewExtension<Interception>();
        //1.TransparentProxyInterceptor
        //container.Configure<Interception>().SetInterceptorFor<IPerson>(new TransparentProxyInterceptor());
        //2.InterfaceInterceptor (使用1,2,3均可,这种侵入性最小)
        container.Configure<Interception>().SetInterceptorFor<IPerson>(new InterfaceInterceptor());
        //3.VirtualMethodInterceptor
        //container.Configure<Interception>().SetInterceptorFor<Person>(new VirtualMethodInterceptor());
        container.RegisterType<IPerson, Person>();
        container.Resolve<IPerson>().Say();
    }
    Console.ReadKey();
}

转载于:https://www.cnblogs.com/chenyishi/p/9676011.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/451255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bootstrap validator 提供了哪些验证函数

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 目前提供的校验方法有&#xff1a; "notEmpty" : "不能为空", "password" : "请输入正确的密码&q…

帕累托分布(Pareto distributions)、马太效应

什么是帕累托分布 帕累托分布是以意大利经济学家维弗雷多帕雷托命名的。 是从大量真实世界的现象中发现的幂次定律分布。这个分布在经济学以外&#xff0c;也被称为布拉德福分布。 帕累托因对意大利20%的人口拥有80%的财产的观察而著名&#xff0c;后来被约瑟夫朱兰和其他人概括…

两个class写在同一个java文件中

第一种&#xff1a; 一个public类&#xff0c;多个非public类&#xff0c;例如&#xff1a;public class A&#xff5b;&#xff5d;class B&#xff5b;&#xff5d;第二个class前面不能加public。 第二种&#xff1a; 第二种是内部类&#xff0c;写在公共类体里面的&#xff…

微信小程序的一些数据调用方式

1.模板数据的调用 一张图了解一下在wxml页调用预先定义好的模板&#xff1a; 可以看到上面调用了两个模板&#xff0c;数据调用却是不同的&#xff0c;obj是一个对象&#xff0c;对象内包含多个键值对形式的数据&#xff1b; tabbar是一个一维数组&#xff0c;每个数组项又都是…

手机厂商探路互联网:硬件高利润时代已成历史

华为消费者业务集团CEO兼终端公司董事长余承东近日出席“2012年全球移动互联网大会”期间证实&#xff0c;华为计划与奇虎360合作推出一款智能手机。 余承东表示&#xff0c;华为终端将尝试与多家互联网公司就智能手机业务展开合作&#xff0c;但他未透露与奇虎360合作的更多细…

解决:按截图 ctrl+alt+a QQ聊天窗口就自动最小化(QQ以外的可以截图)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、问题如题 &#xff0c;想截图QQ聊天记录都不行 二、 解决方法&#xff1a; 如图找到QQ截图按钮&#xff0c;点击下拉倒三角&…

数据库备份DBS商业化发布

数据库备份DBS商业化发布将在2018年7月11日 15:00-16:00直播&#xff0c;敬请关注&#xff01; 数据库备份DBS为数据库提供连续数据保护、低成本的备份服务。 它可以为多种环境的数据提供强有力的保护&#xff0c;包括企业数据中心、其他云厂商及公共云。数据库备份提供数据备份…

堡垒机(跳板机)

堡垒机&#xff08;跳板机&#xff09;&#xff1f;现在一定规模互联网企业&#xff0c;往往都拥有大量服务器&#xff0c;如何安全并高效的管理这些服务器是每个系统运维或安全运维人员必要工作。现在比较常见的方案是搭建堡垒机环境作为线上服务器的入口&#xff0c;所有服务…

2018-09-18

12.1 LNMP架构介绍 和LAMP不同的是&#xff0c;提供web服务的是Nginx并且php是作为一个独立服务存在的&#xff0c;这个服务叫做php-fpmNginx直接处理静态请求&#xff0c;动态请求会转发给php-fpm12.2 MySQL安装 二进制免编译包安装 [rootlocalhost ~]# cd /usr/local/src/ [r…

举例说明Java中代码块的执行顺序

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 结论 这里先把整理好的结论抛给大家&#xff0c;然后我在写个程序来验证我们的结论。在Java类被new的过程中&#xff0c;执行顺序如…

Google 正式开源 Jib ,帮助 Java 应用快速容器化

Google 本周宣布开源一款新的 Java 工具 Jib &#xff0c;旨在让开发者使用他们熟悉的工具更轻松地将 Java 应用程序容器化。在7月9日发布的博客文章中&#xff0c;Google 软件工程师 Appu Goundan 和 Qingyang Chen 将 Jib 描述为一个容器镜像构建器&#xff0c;旨在处理将 Ja…

“公敌”京东:众同行将其拖入价格战

倒京东语录 当当网董事长李国庆&#xff1a; 京东的资金只能维持到8月至12月。当当网是赚一个花两个&#xff0c;而京东则是赚一个花四个。 苏宁电器董事长张近东&#xff1a; 我至今没有看见过哪个企业能通过这种方式取得最后胜利。这种违背正常商业逻辑的做法&#xff0c…

跨域与跨域访问

什么是跨域 跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。跨域的严格一点的定义是&#xff1a;只要 协议&#xff0c;域名&#xff0c;端口有任何一个的不同&#xff0c;就被当作是跨域 为什么浏览器要限制跨域访…

thymeleaf 使用javascript定义数组报错

js中免不了的要用的数组&#xff0c;一维的二维的三维的 但是当用到thymeleaf作为模版时候会有一些坑&#xff0c;导致数组不能用 org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "{checkbox: true, fixed: true}, {field: origi…

解决:Failed to execute goal on project aopcore: Could not resolve dependencies for project com.cmos:

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、问题描述 maven工程 jar包无法下载&#xff0c;报错如下 &#xff1a; [ERROR] Failed to execute goal on project aopcore: Cou…

从Xbox和Zune中学到的四门创业课

导读&#xff1a;微软前娱乐与设备部门总裁Robbie Bach领导他的团队&#xff0c;实现了Xbox的畅销。然而&#xff0c;他领导该部门推出的Zune音乐播放器&#xff0c;却没那么成功。从Robbie这两个经历中&#xff0c;我们们能学到什么&#xff1f;本文是Robbie自己的总结&#x…

服务容错保护断路器Hystrix之七:做到自动降级

从《高可用服务设计之二&#xff1a;Rate limiting 限流与降级》中的“自动降级”中&#xff0c;我们这边将系统遇到“危险”时采取的整套应急方案和措施统一称为降级或服务降级。想要帮助服务做到自动降级&#xff0c;需要先做到如下几个步骤&#xff1a; 可配置的降级策略&am…

from表单提交和JSON区别

form表单是“键值对”的数据格式&#xff0c;例如&#xff1a; a1&b2&c3 而json格式则与之不同&#xff0c;如下&#xff1a; {"a":1,"b":2,"c":3} 传递的数据比较简单&#xff0c;那么两种方式基本上没什么大区别&#xff08;当然后台接…

在一个数组中,如何确定所需元素在数组中的位置.

package wac.wev.LianXi; public class CiShu {public static void main(String[] args){//创建一个数组int[] arr {101,23,123,34,13};int y Yuan(arr,13);System.out.println(y);}//1)明确返回值:int//2)明确形式参数:int[] arr 和 int value(value表示所需元素)public stati…

Java实现Excel导入数据库,数据库中的数据导入到Excel

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 实现的功能&#xff1a; Java实现Excel导入数据库&#xff0c;如果存在就更新数据库中的数据导入到Excel1、添加jxl.jar mysql-connect…