4

.NET知识梳理——8.AOP

 2 years ago
source link: https://www.cnblogs.com/Olive116/p/12451740.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

1. AOP

AOP:允许开发者动态的修改静态的OO模型,就像现实生活中对象在生命周期中会不断的改变自身。   

AOP是一种编程思想,是OOP思想的补充

1.1        AOP面向切面编程

1.1.1  AOP有以下好处

1.1.1.1      聚焦核心业务逻辑

权限/异常/日志/缓存/事务等通用功能可以通过AOP方式添加,程序设计简单,

1.1.1.2      功能动态扩展

集中管理,代码复用;规范化;

1.1.2  实现AOP的多种方式

l  静态实现--装饰器/代理模式

l  动态实现--Remoting/Castle(Emit)

l  静态织入--PostSharp(收费)--扩展编译工具,生成的加入额外代码

l  依赖注入容器的AOP扩展(开发)

l  MVC的Filter--特性标记,然后该方法执行前/后就多了逻辑

invoker调用中心--负责反射调用方法--检查特性--有则执行额外逻辑

1.2        静态AOP实现

静态AOP 可以通过装饰器模式或代理模式进行编码实现。

1.2.1  装饰器模式实现

/// <summary>

    /// 装饰器模式实现静态代理

    /// </summary>

    public class DecoratorAOP

        public static void Show()

            User user = new User()

                Name = "Olive",

                Password = "116"

            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:{user.Name},Password:{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);

            private void BeforeProceed(User user)

                Console.WriteLine("方法执行前");

            private void AfterProceed(User user)

                Console.WriteLine("方法执行后");

1.2.2  代理模式实现

/// <summary>

    /// 代理模式实现静态代理

    /// AOP在方法前后增加自定义的方法

    /// </summary>

    public class ProxyAOP

        public static void Show()

            User user = new User()

                Name = "XF",

                Password = "1165"

            IUserProcessor processor = new UserProcessor();

            processor.RegUser(user);

            Console.WriteLine("****************************");

            processor = new ProxyUserProcessor();

            processor.RegUser(user);

        public interface IUserProcessor

            void RegUser(User user);

        public class UserProcessor : IUserProcessor

            public void RegUser(User user)

                Console.WriteLine($"用户已注册,Name:{user.Name},Password:{user.Password}");

        /// <summary>

        /// 代理模式去提供一个AOP功能

        /// </summary>

        public class ProxyUserProcessor : IUserProcessor

            private IUserProcessor _UserProcessor = new UserProcessor();

            public void RegUser(User user)

                BeforeProceed(user);

                this._UserProcessor.RegUser(user);

                AfterProceed(user);

            private void BeforeProceed(User user)

                Console.WriteLine("方法执行前");

            private void AfterProceed(User user)

                Console.WriteLine("方法执行后");

1.3        动态代理AOP实现

动态AOP可以通过Remoting/Castle(Emit)是实现。

1.3.1  Remoting实现

/// 使用.Net Remoting/RealProxy 实现动态代理

    /// 局限在业务类必须是继承自MarshalByRefObject类型

    public class RealProxyAOP

        public static void Show()

            User user = new User()

                Name = "XF",

                Password = "116"

            UserProcessor processor = new UserProcessor();

            processor.RegUser(user);

            Console.WriteLine("************************");

            UserProcessor userProcessor = TransparentProxy.Create<UserProcessor>();

            userProcessor.RegUser(user);

        public interface IUserProcessor

            void RegUser(User user);

        public class XFRealProxy<T> : RealProxy

            private T t;

            public XFRealProxy(T target) : base(typeof(T))

                this.t = target;

            public override IMessage Invoke(IMessage msg)

                BeforeProceede(msg);

                IMethodCallMessage callMessage = (IMethodCallMessage)msg;

                object returnValue = callMessage.MethodBase.Invoke(this.t, 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("方法执行后加入逻辑");

        public static class TransparentProxy

            public static T Create<T>()

                T instance = Activator.CreateInstance<T>();

                XFRealProxy<T> realProxy = new XFRealProxy<T>(instance);

                T transparentProxy = (T)realProxy.GetTransparentProxy();

                return transparentProxy;

        /// <summary>

        /// 继承MarshalByRefObject父类,在支持远程处理的应用程序中,允许跨应用程序域边界访问对象。

        /// </summary>

        public class UserProcessor : MarshalByRefObject, IUserProcessor

            public void RegUser(User user)

                Console.WriteLine($"用户已注册,用户名称{user.Name},密码:{user.Password}");

1.3.2  Castle实现

/// <summary>

    /// 使用Castle\DynamicProxy实现动态代理

    /// 方法是虚方法

    /// </summary>

    public class CastleProxyAOP

        public static void Show()

            User user = new User()

                Name = "XF",

                Password = "12345"

            ProxyGenerator generator = new ProxyGenerator();

            XFInterceptor interceptor = new XFInterceptor();

            UserProcessor userProcessor = generator.CreateClassProxy<UserProcessor>(interceptor);

            userProcessor.RegUser(user);

        public interface IUserProcessor

            void RegUser(User user);

        public class UserProcessor : IUserProcessor

            public virtual void RegUser(User user)

                Console.WriteLine($"用户注册,Name {user.Name},Password {user.Password}");

        public class XFInterceptor: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("方法执行后");

1.4        Unity、MVC中的AOP

1.4.1  Unitiy实现AOP

需要先在NuGet中引用如下组件:

Unity、Unity.Interception、Unity.Configuration

Unity.Interception.Configuration

1.4.1.1      IUserProcessor

public interface IUserProcessor

        void RegUser(User user);

        User GetUser(User user);

1.4.1.2      UserProcessor

接口的实现类

public class UserProcessor:IUserProcessor

        public void RegUser(User user)

            Console.WriteLine("用户注册");

        public User GetUser(User user)

            return user;

1.4.1.3      MonitorBehavior

AOP添加的性能检测方法

public class MonitorBehavior: Unity.Interception.InterceptionBehaviors.IInterceptionBehavior

        public bool WillExecute

            get { return true; }

        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;

1.4.1.4      LogBeforeBehavior

AOP添加的日志记录方法

public class LogBeforeBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior

        public bool WillExecute

            get { return true; }

        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);

1.4.1.5      ParameterCheckBehavior

AOP添加的参数检查方法

public class ParameterCheckBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior

        public bool WillExecute { get { return true; } }

        public IEnumerable<Type> GetRequiredInterfaces()

            return Type.EmptyTypes;

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)

            Console.WriteLine("ParameterCheckBehavior");

            User user = input.Inputs[0] as User;

            if (user.Password.Length < 3)

                return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于3位"));

                Console.WriteLine("参数检测无误");

                return getNext().Invoke(input, getNext);

1.4.1.6      CachingBehavior

AOP添加的缓存方法

public class CachingBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior

        public bool WillExecute

            get { return true; }

        public IEnumerable<Type> GetRequiredInterfaces()

            return Type.EmptyTypes;

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)

            Console.WriteLine("CachingBehavior");

            if (input.MethodBase.Name.Equals("GetUser"))

                return input.CreateMethodReturn(new User() { Id = 116, Name = "XF" });

            return getNext().Invoke(input, getNext);

1.4.1.7      ExceptionLoggingBehavior

AOP添加的异常记录方法

public class ExceptionLoggingBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior

        public bool WillExecute

            get { return true; }

        public IEnumerable<Type> GetRequiredInterfaces()

            return Type.EmptyTypes;

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)

            Console.WriteLine("ExceptionLoggingBehavior");

            IMethodReturn methodReturn = getNext().Invoke(input, getNext);

            if (methodReturn.Exception == null)

                Console.WriteLine("无异常");

                Console.WriteLine($"异常:{methodReturn.Exception.Message}");

            return methodReturn;

1.4.1.8      LogAfterBehavior

AOP添加的日志记录方法

public class LogAfterBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior

        public bool WillExecute

            get { return true; }

        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().Invoke(input, getNext);

            Console.WriteLine("LogAfterBehavior" + methodReturn.ReturnValue);

            return methodReturn;

1.4.1.9      UnityConfigAOP

public class UnityConfigAOP

        public static void Show()

            User user = new User()

                Name = "XF",

                Password = "116"

       #region配置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 configurationSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);

            configurationSection.Configure(container, "AOPContainer");

            #endregion

            IUserProcessor processor = container.Resolve<IUserProcessor>();

            processor.RegUser(user);

            processor.GetUser(user);


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK