面向切面编程AOP

一、传统的面向对象编程OOP

万物皆对象,专注于类与类之间的交互,由类组成各种功能,功能组咸亨组件,组件又组成系统,适合做大型项目。
但是,由于类是静态的,封闭的,任何需求的变化都会对其带来影响,而在项目的开发过程中,良好的设计是尽量避免对已有类型的更改,因此再前辈的经验中,总结了GOF23种设计模式, 虽然设计模式原则可以解决类与类之间的交互稳定,但如果类的自身变化,需要增加功能需求,则设计模式也解决不了,因此也就出现了面向切面编程的思想了。

二、面向切面编程AOP

面向切面编程,实际上是对OOP的一种补充
允许通过外部方式来修改对象,可以在不破坏类型封装的前提下,去提供新的功能;
AOP只是增加通用逻辑,而不实现核心业务,核心业务还是放在业务类上实现,比如事务、日志、异常、权限、校验、缓存等等。

三、AOP的实现方式:

1. 静态AOP

  • 使用装饰器模式
public interface IUserService
{
    void Register(User user);
}
public class UserService : IUserService
{
    public void Register(User user)
    {
        Console.WriteLine("用户已注册。Name:{0},PassWord:{1}", user.Name, user.Password);
    }
}

/// <summary>
/// 使用装饰器模式提供一个AOP功能
/// </summary>
public class UserServiceDecorator : IUserService
{
    private IUserService UserService { get; set; }
    public UserServiceDecorator(IUserService userService)
    {
        UserService = userService;
    }

    public void Register(User user)
    {
        BeforeProceed(user);

        this.UserProcessor.RegUser(user);

        AfterProceed(user);
    }

    /// <summary>
    /// 业务逻辑之前
    /// </summary>
    /// <param name="user"></param>
    public void BeforeProceed(User user)
    {
        Console.WriteLine("方法执行前");
    }
    /// <summary>
    /// 业务逻辑之后
    /// </summary>
    /// <param name="user"></param>
    public void AfterProceed(User user)
    {
        Console.WriteLine("方法执行后");
    }
}

  • 使用简单代理模式
public abstract class UserService
{
	public abstract void Register(User user);
}

public class WebUserService : UserService
{
	public override void Register(User user)
	{
		Console.WriteLine("用户已注册!");
	}
}

/// <summary>
/// 使用代理模式实现AOP
/// </summary>
public class UserProxy : UserService
{
	private WebUserService webUserService;

	public override void Register(User user)
	{
		if(webUserService == null)
		{
			webUserService = new WebUserService();
		}

		webUserService.Register(user);
	}

	public void Before()
	{

	}

	public void After()
	{

	}
}

2. 动态代理实现AOP (RealProxy/emit生成/Unity)

  • 使用 .Net Remoting/RealProxy实现动态代理,此方式局限在于业务类必须是继承自MarshalByRefObject类型的类
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
public class ProxyAOP
{
    public static void Show()
     {
        User user = new User() {
        	Name = "Lucas",
            Password = "123456"
        };
            
        UserService UserService = TransparentProxy.Create<UserService>();
        UserService.RegUser(user);
        int result = UserService.GetUserId();
     }

    /// <summary>
    /// 真实代理
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class MyRealProxy<T> : RealProxy
    {
        private T tTarget;
        public MyRealProxy(T target)
                : base(typeof(T))
            {
                this.tTarget = target;
            }

        public override IMessage Invoke(IMessage msg)
        {
            BeforeProceede(msg);

            IMethodCallMessage callMessage = (IMethodCallMessage)msg;
            object returnValue = callMessage.MethodBase.Invoke(this.tTarget, callMessage.Args);

            AfterProceede(msg);

            return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);
        }
        public void BeforeProceede(IMessage msg)
        {
            Console.WriteLine("方法执行前可以加入的逻辑");
        }
        public void AfterProceede(IMessage msg)
        {
            Console.WriteLine("方法执行后可以加入的逻辑");
        }
    }

    /// <summary>
    /// 透明代理
    /// </summary>
    public static class TransparentProxy
    {
        public static T Create<T>()
        {
            T instance = Activator.CreateInstance<T>();
            MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);
            T transparentProxy = (T)realProxy.GetTransparentProxy();
            return transparentProxy;
        }
    }


    public interface IUserService
    {
        void RegUser(User user);
        int GetUserId();
    }

    /// <summary>
    /// 必须继承自MarshalByRefObject父类
    /// </summary>
    public class UserService : MarshalByRefObject, IUserService
    {
        public void RegUser(User user)
        {
            Console.WriteLine("用户已注册。用户名称{0} Password{1}", user.Name, user.Password);
        }

        public int GetUserId()
        {
            return 123;
        }
    }
}

  • 使用Castle\DynamicProxy 实现动态代理,其局限性为业务类的方法必须为虚方法
using Castle.DynamicProxy;

public class CastleProxyAOP
{
    public static void Show()
    {
        User user = new User()
        {
            Name = "Lucas",
            Password = "123456"
        };
        
        ProxyGenerator generator = new ProxyGenerator();
        MyInterceptor interceptor = new MyInterceptor();
        UserService UserService = generator.CreateClassProxy<UserService>(interceptor);
        UserService.RegUser(user);
    }
    
    public interface IUserService
    {
        void RegUser(User user);
    }

    public class UserService : IUserService
    {
        /// <summary>
        /// 必须带上virtual
        /// </summary>
        /// <param name="user"></param>
        public virtual void RegUser(User user)
        {
            Console.WriteLine($"用户已注册。Name:{user.Name},PassWord:{user.Password}");
        }
    }

    /// <summary>
    /// 添加的通用逻辑在此类中实现,继承IItercepter类
    /// </summary>
    public class MyInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            PreProceed(invocation);
            invocation.Proceed();
            PostProceed(invocation);
        }
        public void PreProceed(IInvocation invocation)
        {
            Console.WriteLine("方法执行前");
        }

        public void PostProceed(IInvocation invocation)
        {
            Console.WriteLine("方法执行后");
        }
    }
}

  • 使用Unity实现动态代理,针对整个类而言,不具体到某个方法,如果想要单独为某个方法增加,在handler中检测如果是其他方法的话则直接返回就行了,当然也有其他的方式,可以使用一下的几个方式实现针对某个方法的。
    TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject…不建议用
    VirtualMethod:直接在类的方法上进行标记,但这个方法必须是虚方法(就是方法要带virtual关键字)
    InterfaceInterceptor:在接口的方法上进行标记,这样继承这个接口的类里实现这个接口方法的方法就能被拦截
using Unity;
using Unity.Interception.ContainerIntegration;
using Unity.Interception.Interceptors.InstanceInterceptors.InterfaceInterception;
using Unity.Interception.PolicyInjection.Pipeline;
using Unity.Interception.PolicyInjection.Policies;

public class UnityAOP
{
    public static void Show()
    {
        User user = new User() {
            Name = "Lucas",
            Password = "123456"
        };
        
        IUnityContainer container = new UnityContainer();//声明一个容器
        container.RegisterType<IUserService, UserService>();//声明UnityContainer并注册IUserService
        IUserService processor = container.Resolve<IUserService>();
        processor.RegUser(user);//调用

        container.AddNewExtension<Interception>().Configure<Interception>()
           .SetInterceptorFor<IUserService>(new InterfaceInterceptor());

        IUserService UserService = container.Resolve<IUserService>();
        UserService.RegUser(user);//调用
        UserService.GetUser(user);//调用

    }

    #region 特性对应的行为
    public class UserHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
             User user = input.Inputs[0] as User;
             if (user.Password.Length < 10)
             {
                return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位"));
             }

             IMethodReturn methodReturn = getNext()(input, getNext);  //等价于getNext.Invoke().Invoke(input, getNext);

             return methodReturn;
        }
    }

    public class LogHandler : ICallHandler
    {
        public int Order { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="input">方法调用的参数列表</param>
        /// <param name="getNext"></param>
        /// <returns></returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                User user = input.Inputs[0] as User;
                string message = $"RegUser:Username:{user.Name},Password:{user.Password}";
                Console.WriteLine("日志已记录,Message:{0},Ctime:{1}", message, DateTime.Now);
                return getNext()(input, getNext);
            }
    }

    public class ExceptionHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                IMethodReturn methodReturn = getNext()(input, getNext);
                if (methodReturn.Exception == null)
                {
                    Console.WriteLine("无异常");
                }
                else
                {
                    Console.WriteLine($"异常:{methodReturn.Exception.Message}");
                }
                return methodReturn;
            }
    }

    public class AfterLogHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                IMethodReturn methodReturn = getNext()(input, getNext);
                User user = input.Inputs[0] as User;
                string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
                Console.WriteLine("完成日志,Message:{0},Ctime:{1},计算结果{2}", message, DateTime.Now, methodReturn.ReturnValue);
                return methodReturn;
            }
    }
    #endregion 特性对应的行为

    #region 特性
    public class UserHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            ICallHandler handler = new UserHandler() { Order = this.Order };
            return handler;
        }
    }

    public class LogHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new LogHandler() { Order = this.Order };
        }
    }

    public class ExceptionHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new ExceptionHandler() { Order = this.Order };
        }
    }

    public class AfterLogHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new AfterLogHandler() { Order = this.Order };
        }
    }
    #endregion 特性

    #region 业务
    [UserHandlerAttribute(Order = 1)]
    [ExceptionHandlerAttribute(Order = 3)]
    [LogHandlerAttribute(Order = 2)]
    [AfterLogHandlerAttribute(Order = 5)]
    public interface IUserService
    {
        void RegUser(User user);
        User GetUser(User user);
    }

    public class UserService : IUserService
    {
        public void RegUser(User user)
        {
            Console.WriteLine("用户已注册。");
            //throw new Exception("11");
        }

        public User GetUser(User user)
        {
            return user;
        }
    }
    #endregion 业务


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值