Spring.NET学习笔记12——面向切面编程(基础篇) Level 300

  AOP面向切面编程(Aspect Oriented Programming的缩写),是OOP(面向对象编程)的一种延续形式。是通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术,它从一个不同于OOP的角度来看待程序的结构:OOP将应用程序分解为一系列表现为继承关系的对象;AOP 则把程序分解为一系列方面(aspects)或者关注点(concerns)。AOP将诸如事务管理等本来横向分布在多个对象中的关注点进行了模块化处理(这些关注点也常称为横切(crosscutting)关注点)。在Spring.NET中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

  下面我举个例子来说明这一切:

  场景:业务类CompanyManager在调用Save方法的时候需要调用SecurityManager类判断权限是否足够(图1)。

图1

 

  准备条件:

    public class CompanyDao
ExpandedBlockStart.gifContractedBlock.gif    
{
        
public void Save()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            Console.WriteLine(
"保存数据");
        }

    }

 

    public interface ICompanyManager
ExpandedBlockStart.gifContractedBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
string UserName getset; }

        
void Save();
    }

 

    public interface ISecurityManager
ExpandedBlockStart.gifContractedBlock.gif    
{
        
bool IsPass(string userName);
    }

 

ContractedBlock.gifExpandedBlockStart.gifSecurityManager
    public class SecurityManager : ISecurityManager
ExpandedBlockStart.gifContractedBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 判断权限
        
/// </summary>
        
/// <param name="userName"></param>
        
/// <returns></returns>

        public bool IsPass(string userName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return userName == "admin";
        }

    }

 

  第一种实现方式,我们通常会这样做:直接在CompanyManager类中调用ISecurityManager接口的IsPass方法判断权限。

 

ContractedBlock.gifExpandedBlockStart.gifSimpleCompanyManager
public class SimpleCompanyManager : ICompanyManager
ExpandedBlockStart.gifContractedBlock.gif    
{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
可通过外部注入的属性#region 可通过外部注入的属性

ExpandedSubBlockStart.gifContractedSubBlock.gif        
public string UserName getset; }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
public CompanyDao Dao getset; }

        
#endregion


        
public void Save()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//判断权限
            ISecurityManager security = new SecurityManager();
            
if (security.IsPass(UserName))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
//执行业务方法
                
//.
                
//调用DAO层方法
                Dao.Save();
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
//执行其它业务方法
                Console.WriteLine("您没有该权限");
            }

        }

    }

 

  这样CompanyManager类与ISecurityManagerSecurityManager会发生业务性耦合。聪明的朋友会发现在GOF(设计模式)中有一种模式(代理模式)可以解除这种耦合。

  第二种实现方式,代理模式(Proxy Pattern):什么是代理模式?是给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入(图2)。
图2

ContractedBlock.gifExpandedBlockStart.gifCompanyManager
    public class CompanyManager : ICompanyManager
ExpandedBlockStart.gifContractedBlock.gif    
{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
可通过外部注入的属性#region 可通过外部注入的属性

ExpandedSubBlockStart.gifContractedSubBlock.gif        
public string UserName getset; }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
public CompanyDao Dao getset; }

        
#endregion


        
public void Save()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//执行业务方法
            
//.
            
//调用DAO层方法
            Dao.Save();
        }

    }

 

ContractedBlock.gifExpandedBlockStart.gifCompanyProxyManager
    public class CompanyProxyManager : ICompanyManager
ExpandedBlockStart.gifContractedBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public string UserName getset; }

        
private ICompanyManager target = new CompanyManager();

        
public void Save()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//判断权限
            ISecurityManager security = new SecurityManager();
            
if (security.IsPass(UserName))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
//调用目标对象Save方法
                target.Save();
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Console.WriteLine(
"您没有该权限");
            }

        }

    }

 

  这样,CompanyManager类就不必与判断权限的类SecurityManager耦合,但是这种方式实现起来比较麻烦。
 

  第三种实现方式,Spring.NET提供的AOP:AopAlliance.Intercept.IMethodInterceptor接口和ProxyFactory类的组合。

ContractedBlock.gifExpandedBlockStart.gifAroundAdvice
    public class AroundAdvice : IMethodInterceptor
ExpandedBlockStart.gifContractedBlock.gif    
{
        
//权限系统类(可外部注入)
        private ISecurityManager manager = new Service.SecurityManager();

        
public object Invoke(IMethodInvocation invocation)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//拦截Save方法
            if (invocation.Method.Name == "Save")
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                ICompanyManager target 
= (ICompanyManager)invocation.Target;

                
return manager.IsPass(target.UserName) ? invocation.Proceed() : null;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return invocation.Proceed();
            }

        }

    }

 

ContractedBlock.gifExpandedBlockStart.gifProgram
    class Program
ExpandedBlockStart.gifContractedBlock.gif    
{
        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ExpandedSubBlockStart.gifContractedSubBlock.gif            ICompanyManager target 
= new CompanyManager() { Dao = new CompanyDao(), UserName = "admin" };
            
            ProxyFactory factory 
= new ProxyFactory(target);
            factory.AddAdvice(
new AroundAdvice());

            ICompanyManager manager 
= (ICompanyManager)factory.GetProxy();
            manager.Save();

            Console.ReadLine();
        }

    }

 

  输出:保存数据
  

 

  Spring.NET利用System.Reflection.Emit命名空间下的类在运行时动态创建IL代码来生成AOP代理。这使得代理(的创建)非常高效,并且不受任何继承层次的限制。

 

  参考:Spring.NET中文手册

  李会军博客代理模式http://www.cnblogs.com/terrylee/archive/2006/05/18/403382.html

 

  代码下载
 

 

  返回目录

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

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

相关文章

React开发(158):ant design级联回显 直接传入数组

ReactDOM.render(<CascaderdefaultValue{[zhejiang, hangzhou, xihu]}options{options}onChange{onChange}/>,mountNode, );

vue-cli3使用svg图标的详细步骤

1.安装依赖 npm install svg-sprite-loader -D2.在vue.config.js里添加配置 module.exports{chainWebpack: config > {const svgRule config.module.rule("svg"); svgRule.uses.clear();svgRule.use("svg-sprite-loader").loader("svg-sprite…

网络工程师的忠告

诸位&#xff0c;咱当网络工程师也是几年了&#xff0c;不算有出息&#xff0c;环顾四周&#xff0c;也没有看见几个有出息的&#xff01;回顾工程师生涯&#xff0c;感慨万千&#xff0c;愿意讲几句掏心窝子的话&#xff0c;也算给咱们师弟师妹们提个醒&#xff0c;希望他们比…

python模拟登陆163邮箱并获取通讯录

From: http://hi.baidu.com/fc_lamp/blog/item/2466d1096fcc532de8248839.html python模拟登陆163邮箱并获取通讯录 #-*- coding:UTF-8 -*-import urllib,urllib2,cookielibimport xml.etree.ElementTree as etree #xml解析类class Login163:#伪装browserheader {User-Agent:…

【BZOJ】【3850】ZCC Loves Codefires

贪心 就跟NOIP2012国王游戏差不多&#xff0c;考虑交换相邻两题的位置&#xff0c;对其他题是毫无影响的&#xff0c;然后看两题顺序先后哪个更优。sort即可。 WA了一次的原因&#xff1a;虽然ans开的是long long&#xff0c;但是在这一句:anstime*a[i].k;时&#xff0c;还是需…

Element-UI中关于table表格的那些骚操作

最近的项目中使用到element-ui组件库&#xff0c;由于做的是后台管理系统&#xff0c;所以经常需要操作表格&#xff0c;编辑样式的过程中遇到一些问题&#xff0c;官网针对table给出了很多的api&#xff0c;自己可以自定义&#xff0c;基本能满足产品需求&#xff0c;但是没有…

讯闪菜单密码去除方法

网上有很多关于讯闪菜单密码去除或补丁软件&#xff0c;但都没有把原理说出来&#xff0c;下面介绍方法&#xff1a;打开&#xff1a;讯闪目录\data\ClientCfg.ini查找&#xff1a;分类辅助d41d8cd98f00b204e9800998ecf8427e把分类辅助替换为&#xff1a;d41d8cd98f00b204e9800…

详细介绍 Qt Creator 快捷捷应用

From: http://www.zhujiangroad.com/program/Symbian/25211.html Qt Creator 快捷捷应用是本文要介绍的内容 。以前经常用VSQT的方式来学习QT&#xff0c;VS确实挺强大&#xff0c;不过每次编译Qt&#xff0c;太浪费时间&#xff0c;而且如果重装系统或者VS都必须重新编译&…

asp IIS部署An error occurred on the server when processing the URL错误提示解决

An error occurred on the server when processing the URL. Please contact the system administrator.If you are the system administrator please click here to find out more about this error.其实这是 IIS7 对 ASP 程序发送的一个脚本错误消息&#xff0c;只要是程序中…

修饰符.lazy .number .trim

1、lazy v-model 在每次 input 事件触发后将输入框的值与数据进行同步,也就是在失去焦点或者按下回车键时才更新 <template><div><p>.lazy修饰符</p><input type"text" v-model.lazy"val"><p>{{ val }}</p><…

使用Phar来打包发布PHP程序

简单来说&#xff0c;Phar就是把Java界的jar概念移植到了PHP界。 Phar可以将一组PHP文件进行打包&#xff0c;还可以创建默认执行的stub&#xff08;或者叫做 bootstrap loader&#xff09;&#xff0c;Phar可以选择是否进行压缩&#xff0c;可选gzip和bzip2格式。 下面举例说明…

asp.net动态加载css

谁如果有更直接的方法&#xff0c;请不吝赐教。也不知道.net有什么方法可以直接更换css <% Page Language"C#"AutoEventWireup"true"CodeFile"Default.aspx.cs"Inherits"_Default"%><!DOCTYPE html PUBLIC "-//W3C//DTD…

Qt Creator 使用技巧

From: http://www.developer.nokia.com/Community/Wiki/Qt_Creator_%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7 Qt Creator 使用技巧 简介 Qt Creator 作为Qt 开发的IDE&#xff0c;支持Qt 开发&#xff0c;及QML开发&#xff0c;能很好的发挥Qt 跨平台的特点&#xff0c;这里列举一…

Ubuntu下实现eth0与wlan0完美桥接

操作系统Ubuntu14.04LTS 1.搭载网桥模块 sudo apt-get install bridge-utils安装软件包 modprobe bridge//网上参考步骤&#xff0c;加载网桥模块&#xff0c;实际未用 cho "1">/proc/sys/net/ipv4/ip_forward//网上参考步骤&#xff0c;开启Ip转发功能&#xff0…

前端利用CryptoJS进行AES对称加解密(16进制编码)

加密相关JS https://www.npmjs.com/package/crypto-js 引入JS 使用示例&#xff1a; 附上原文代码方便大家自由使用 //加密 let key CryptoJS.enc.Utf8.parse(123456789qwertyu);//密钥必须是16位&#xff0c;且避免使用保留字符 let encryptedData CryptoJS.AES.encry…

RTMPT

转自http://www.openred5.com/bbs/viewthread.php?tid196 英文原地址&#xff1a;http://www.joachim-bauch.de/tutorials/red5/SPEC-RTMPT.html/view 等一段时间后我也去整理一个出来&#xff0c;因为现在还没有用到rtmpt&#xff0c;只用到rtmp和rtmpe&#xff0c;所以没有时…

前端学习(3339):ant design中加上icon图标

当需要在 Button 内嵌入 Icon 时&#xff0c;可以设置 icon 属性&#xff0c;或者直接在 Button 内使用 Icon 组件。 如果想控制 Icon 具体的位置&#xff0c;只能直接使用 Icon 组件&#xff0c;而非 icon 属性。 ReactDOM.render(<div><Button type"primary&qu…

Hello Qt(在Linux下编写运行Qt程序)

From: http://www.yafeilinux.com/?p763 <一>Hello Qt小试牛刀&#xff01; 说明&#xff1a;我们需要在Linux下已经安装了Qt。 1.下面是整个程序的详细介绍&#xff1a; #include <QApplication> //第一行是定义一个应用程序类<QApplication>的头文件&…