面向切面编程AOP
最开始接触aop这个概念,是在大学java课程中(具体哪本忘记了,javaweb?)接触到的。当时的理解就是,一个请求过来,自上而下,突然从中间切一刀。从那个图是这样理解的,文字描述的都忘记了。关于aop的博客有好多,在工作中需要用到,我也是看着博客,外加视频学习来理解的。
这篇博客,写的还是蛮详细的。下面只是我自己的总结。
aop不是一种设计模式,而是一种编程思想,和pop,oop一样,是oop的扩展,aop的出现并不能代替oop。
pop,面向过程编程:
符合逻辑思维,线性的处理问题,但是无法应对复杂的系统
oop面向对象编程:
万物皆对象,对象交互完成功能,功能叠加成模块,模块组成系统,才有机会搭建复杂的大型的软件系统。
下面以一个例子来作为对比:
砖块--------墙---------房间---------大厦
类--------功能点------模块---------系统
砖块应该是稳定的,说明是静态,不变的。在程序开发的过程中,类确实会变化的,增加日志/异常/权限/缓存/事务等,只能修改类。
在gof23种设计模式,应对变化的,核心套路是依赖抽象,细节就可以变化,但是只能替换整个对象,没办法把一个类动态改变。
aop面向切面编程:
允许开发者动态的修改静态的oo模型,就像现实生活中对象在生命周期中会不断的改变自身。aop是一种编程思想,是oop思想的补充。
正式因为能够动态的扩展功能,所以在程序设计的时候,就可以有以下好处:
1、聚焦核心业务逻辑,权限/异常/缓存/事务,通过功能可以通过aop方式添加,程序设计简单。
2、动态扩展,集中管理,代码复用,规范化。
下面,用装饰器模式,去实现一个aop功能:
/// <summary> /// 装饰器模式实现静态代理 /// aop 在方法前后增加自定义的方法 /// </summary> public class decoratoraop { public static void show() { user user = new user() { name = "bingle", password = "123123123123" }; iuserprocessor processor = new userprocessor(); processor.reguser(user); console.writeline("***************"); processor = new userprocessordecorator(processor); processor.reguser(user); } public interface iuserprocessor { void reguser(user user); } public class userprocessor : iuserprocessor { public void reguser(user user) { console.writeline("用户已注册。name:{0},password:{1}", user.name, user.password); } } /// <summary> /// 装饰器的模式去提供一个aop功能 /// </summary> public class userprocessordecorator : iuserprocessor { private iuserprocessor _userprocessor { get; set; } public userprocessordecorator(iuserprocessor userprocessor) { this._userprocessor = userprocessor; } public void reguser(user user) { beforeproceed(user); this._userprocessor.reguser(user); afterproceed(user); } /// <summary> /// 业务逻辑之前 /// </summary> /// <param name="user"></param> private void beforeproceed(user user) { console.writeline("方法执行前"); } /// <summary> /// 业务逻辑之后 /// </summary> /// <param name="user"></param> private void afterproceed(user user) { console.writeline("方法执行后"); } } }
实现aop的多种方式:
1、静态实现----装饰器/代理模式
2、动态实现----remoting/castlet
3、静态植入---postsharp(收费)----扩展编译工具,生成的加入额外代码
4、依赖注入容器的aop扩展(unity)
5、mvc的filter---特性标机,然后该方法执行前后就多了逻辑
之前看到有的人认为,在.net core中的中间件,也是aop的一种实现。也有一些人认为不是。博主认为,.net core中的中间件并不是aop的一种实现。等后续随笔记载到中间件的时候,再去详细说明吧。
依赖注入容器的aop扩展(扩展)
基于配置文件的unity。
首先,用nuget引入unity想换的程序集
下面是配置文件:
<configuration> <configsections> <section name="unity" type="microsoft.practices.unity.configuration.unityconfigurationsection, unity.configuration"/> <!--microsoft.practices.unity.configuration.unityconfigurationsection--> </configsections> <unity> <sectionextension type="microsoft.practices.unity.interceptionextension.configuration.interceptionconfigurationextension, unity.interception.configuration"/> <containers> <container name="aopcontainer"> <extension type="interception"/> <register type="myaop.unityway.iuserprocessor,myaop" mapto="myaop.unityway.userprocessor,myaop"> <interceptor type="interfaceinterceptor"/> <interceptionbehavior type="myaop.unityway.monitorbehavior, myaop"/> <interceptionbehavior type="myaop.unityway.logbeforebehavior, myaop"/> <interceptionbehavior type="myaop.unityway.parametercheckbehavior, myaop"/> <interceptionbehavior type="myaop.unityway.cachingbehavior, myaop"/> <interceptionbehavior type="myaop.unityway.exceptionloggingbehavior, myaop"/> <interceptionbehavior type="myaop.unityway.logafterbehavior, myaop"/> </register> </container> </containers> </unity> </configuration>
使用entlib\piab unity 实现动态代理:
public class unityconfigaop { [obsolete] public static void show() { user user = new user() { name = "bingle", password = "1234567890123456789" }; //配置unitycontainer iunitycontainer container = new unitycontainer(); execonfigurationfilemap filemap = new execonfigurationfilemap(); filemap.execonfigfilename = path.combine(appdomain.currentdomain.basedirectory + "cfgfiles\\unity.config"); configuration configuration = configurationmanager.openmappedexeconfiguration(filemap, configurationuserlevel.none); unityconfigurationsection configsection = (unityconfigurationsection)configuration.getsection(unityconfigurationsection.sectionname); configsection.configure(container, "aopcontainer"); iuserprocessor processor = container.resolve<iuserprocessor>(); processor.reguser(user); processor.getuser(user); } }
public class logafterbehavior : iinterceptionbehavior { public ienumerable<type> getrequiredinterfaces() { return type.emptytypes; } public imethodreturn invoke(imethodinvocation input, getnextinterceptionbehaviordelegate getnext) { console.writeline("logafterbehavior"); foreach (var item in input.inputs) { console.writeline(item.tostring());//反射获取更多信息 } imethodreturn methodreturn = getnext()(input, getnext); console.writeline("logafterbehavior" + methodreturn.returnvalue); return methodreturn; } public bool willexecute { get { return true; } } }
/// <summary> /// 不需要特性 /// </summary> public class logbeforebehavior : iinterceptionbehavior { public ienumerable<type> getrequiredinterfaces() { return type.emptytypes; } public imethodreturn invoke(imethodinvocation input, getnextinterceptionbehaviordelegate getnext) { console.writeline("logbeforebehavior"); foreach (var item in input.inputs) { console.writeline(item.tostring());//反射获取更多信息 } return getnext().invoke(input, getnext); } public bool willexecute { get { return true; } } }
public class exceptionloggingbehavior : iinterceptionbehavior { public ienumerable<type> getrequiredinterfaces() { return type.emptytypes; } public imethodreturn invoke(imethodinvocation input, getnextinterceptionbehaviordelegate getnext) { console.writeline("exceptionloggingbehavior"); imethodreturn methodreturn = getnext()(input, getnext); if (methodreturn.exception == null) { console.writeline("无异常"); } else { console.writeline($"异常:{methodreturn.exception.message}"); } return methodreturn; } public bool willexecute { get { return true; } } }
/// <summary> /// 不需要特性 /// </summary> public class cachingbehavior : iinterceptionbehavior { public ienumerable<type> getrequiredinterfaces() { return type.emptytypes; } public imethodreturn invoke(imethodinvocation input, getnextinterceptionbehaviordelegate getnext) { console.writeline("cachingbehavior"); //input.target.gettype().getcustomattributes() if (input.methodbase.name.equals("getuser")) return input.createmethodreturn(new user() { id = 234, name = "eleven" }); return getnext().invoke(input, getnext); } public bool willexecute { get { return true; } } }
/// <summary> /// 性能监控的aop扩展 /// </summary> public class monitorbehavior : iinterceptionbehavior { public ienumerable<type> getrequiredinterfaces() { return type.emptytypes; } public imethodreturn invoke(imethodinvocation input, getnextinterceptionbehaviordelegate getnext) { console.writeline(this.gettype().name); string methodname = input.methodbase.name; stopwatch stopwatch = new stopwatch(); stopwatch.start(); var methodreturn = getnext().invoke(input, getnext);//后续逻辑执行 stopwatch.stop(); console.writeline($"{this.gettype().name}统计方法{methodname}执行耗时{stopwatch.elapsedmilliseconds}ms"); return methodreturn; } public bool willexecute { get { return true; } } }
下一篇: ansible变量