码迷,mamicode.com
首页 > 其他好文 > 详细

AOP系列(一)——ProxyFactoryObject 显式创建AOP代理

时间:2015-08-04 23:07:09      阅读:584      评论:0      收藏:0      [点我收藏+]

标签:aop   代理   

AOP概念

  Aspect Oriented Programming,面向切面编程,可以通过预编译方式和运行期动态代理,实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

前提


  • 了解Spring.NET IOC
  • 熟悉代理模式

  下面我们结合一个具体的例子来了解AOP。

基本情景

技术分享

User类

    /// <summary>
    /// 用户实体,具有姓名和年龄两个属性
    /// </summary>
    public class User
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

IUserService

    public interface IUserService
    {
        //获得用户信息
        void GetUserInfo(User enUser);
    }

UserService

    public class UserService:IUserService
    {
        /// <summary>
        /// 获得用户的信息
        /// </summary>
        /// <param name="enUser">用户实体</param>
        public void GetUserInfo(User enUser)
        {
            //输出用户的姓名和年龄
            Console.WriteLine("姓名:"+enUser .Name+"年龄:"+enUser .Age  );
        }
    }

客户端(控制台应用程序)Program

  • “ new()”出具体的实现——这里我们不采用此方式
    class Program
    {
        static void Main(string[] args)
        {
            //实例化一个实体
            User enUser = new User()
            {
                Name = "Danny",
                Age = 15
            };           
            IUserService userService = new UserService();
            userService.GetUserInfo(enUser);

        }
    }
  • 通过Spring IOC获得具体实现(相当于工厂)
//引入Spring.Core.dll
using Spring.Context;
using Spring.Context.Support;

namespace WithoutAOP
{
    class Program
    {
        static void Main(string[] args)
        {
            //实例化一个实体
            User enUser = new User()
            {
                Name = "Danny",
                Age = 15
            };          

            //获得Spring.IOC容器的上下文
            IApplicationContext context = ContextRegistry.GetContext();
            //根据配置文件中的配置获得业务实现类
            IUserService userService = (IUserService)context.GetObject("userService");
            //调用业务实现类的方法
            userService.GetUserInfo(enUser);
        }
    }
}

配置文件

    <!--Spring配置-->
    <configSections>
        <sectionGroup name="spring">
            <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
            <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
        </sectionGroup>
    </configSections>
    <spring>
        <context>
            <resource uri="config://spring/objects"/>
        </context>
        <objects xmlns="http://www.springframework.net">
            <object id="userService" type="AOPExample.UserService,AOPExample"/>
        </objects>
    </spring>

  现在我们要为已有的业务逻辑增加日志功能。接下来看看AOP如何来实现。
  在了解之前,我们先来了解AOP中的一些术语。

AOP术语

技术分享

  • 目标对象(Target),即我们要代理的对象(UserService),也就是我们要为此对象增加日志功能。
  • 关注点(Concern):如日志功能。日志功能是系统级别的,不可能只在一个对象中增加日志功能。
  • 通知(Advice):在Advice中写日志功能的具体实现。通知类实现不同的接口,如:Before,After……这些决定了日志功能如何添加(切入)到业务逻辑中,是在业务逻辑执行前添加,还是执行后添加。

AOP实现思路

  • 写具体的通知类Advice(实现日志功能)
  • 在配置文件中进行配置

    • 配置生成代理类的方式
    • 配置目标对象(可以直接配置具体的目标对象,也可以通过名称或正则表达式,程序执行后会在容器中寻找到符合条件的对象作为目标对象)

    • 配置通知类

ProxyFactoryObject 显式创建AOP代理

Advice通知类

//引入System.Aop.dll;
using Spring.Aop;       //AOP
using System.Reflection;//反射
namespace AOPExample
{
    /// <summary>
    /// Advice通知类:实现日志功能
    /// </summary>
    public class LogBeforeAdvice:IMethodBeforeAdvice
    {
        /// <summary>
        /// 实现接口IMethodBeforeAdvice中的Before方法,在目标方法执行前执行Before()
        /// </summary>
        /// <param name="method">拦截的方法</param>
        /// <param name="args">方法的参数</param>
        /// <param name="target">拦截的对象</param>
        public void Before(MethodInfo method, object[] args, object target)
        {
            Console.WriteLine("拦截的方法名—>" + method.Name);
            Console.WriteLine("目标对象—>" + target);
            Console.WriteLine("参数—>");

            //如果参数不为空,遍历所有参数并输出
            if (args != null)
            {
                foreach (object arg in args)
                {
                    Console.WriteLine("\t: " + arg);
                }
            }  
        }
    }
}

配置文件

<?xml version="1.0"?>
<configuration>
    <!--Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常。-->
    <!--注释掉此配置节,否则会报上述异常-->
    <!--<startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
    </startup>-->  
    <!--Spring配置-->
    <configSections>
        <sectionGroup name="spring">
            <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
            <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
        </sectionGroup>
    </configSections>

    <spring>
        <context>
            <resource uri="config://spring/objects"/>
        </context>
        <objects xmlns="http://www.springframework.net">
            <!--配置通知类LogBeforeAdvice-->
            <object id="beforeAdvice" type="AOPExample.LogBeforeAdvice,AOPExample"/>         
            <!--通过ProxyFactoryObject 显式创建AOP代理-->
            <object id="userServiceProxy" type="Spring.Aop.Framework.ProxyFactoryObject">
                <!--指定代理的真实对象-->
                <property name="Target">
                    <object type="AOPExample.UserService,AOPExample"/>
                </property>
                <!--指定具体通知类-->
                <property name="InterceptorNames">
                    <list>
                        <!--指定具体通知类,和前面配置的id一致-->
                        <value>beforeAdvice</value>
                    </list>
                </property>
            </object>
        </objects>
    </spring>
</configuration>

客户端

    class Program
    {
        static void Main(string[] args)
        {
            //实例化用户
            User enUser = new User()
            {
                Name ="Jenny",
                Age=15
            };

            //获得Spring容器上下文
            IApplicationContext context = ContextRegistry.GetContext();
            //从配置文件获得由ProxyFactoryObject生成的代理类
            //需要修改客户端,原来是直接调用真实对象,现在是调用代理
            IUserService userServiceProxy = (IUserService)context["userServiceProxy"];
            userServiceProxy.GetUserInfo(enUser);

        }
    }

运行结果
技术分享

总结

  • 优点:通过ProxyFactoryObject 创建代理类,省去自己手动创建代理类;
  • 缺点1:如果有多个目标对象,每个都需要在配置文件中配置;
  • 缺点2:客户端调用时,由原来调用目标对象,变成调用代理对象,需要修改客户端代码。

版权声明:本文为博主原创文章,未经博主允许不得转载。

AOP系列(一)——ProxyFactoryObject 显式创建AOP代理

标签:aop   代理   

原文地址:http://blog.csdn.net/u010924834/article/details/47282809

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!