动态织入的AOP实现

简介: 动态织入的AOP实现,有两种方法: 第一类,借助于Remoting命名空间下的几个类,通过获取当前上下文及反射的机制来实现,这需要被AOP的类需要继承自arshalByRefObject或者ContextBoundObject; 第二类,原理是基于动态代理的思想,即在运行时动态构造一个原有类的子类,这样就可以在子类的重载方法中插入额外代码。

动态织入的AOP实现,有两种方法:

第一类,借助于Remoting命名空间下的几个类,通过获取当前上下文及反射的机制来实现,这需要被AOP的类需要继承自arshalByRefObject或者ContextBoundObject;

第二类,原理是基于动态代理的思想,即在运行时动态构造一个原有类的子类,这样就可以在子类的重载方法中插入额外代码。

这两类方法,都有显著的不足,前者直接要求我们继承固定类,后者呢,除非父类方法被定义为virtual,或者方法定义于某个接口,否则就不能被重载,这就是得“拦截”并不是可以对任意的方法进行的。

动态织入局限于CLR的限制,不能实现对任何方法进行AOP,如果要突破这个限制,只能采用静态织入的方法,静态织入采用。静态织入突破OO设计模式,可以拦截所有的方法甚至构造函数或属性访问器,因为它是直接修改IL。还有,因为它在运行前修改原有程序集,也就基本不存在运行时的性能损失问题了。它的不足,一方面是框架较复杂,实现较麻烦,依赖于对底层的IL指令集的操纵;

一:继承自ContextBoundObject的实现

帮助类:

    public class SecurityAspect : IMessageSink
    {
        internal SecurityAspect(IMessageSink next)
        {
            _next = next;
        }

        private IMessageSink _next;

        public IMessageSink NextSink
        {
            get { return _next; }
        }

        public IMessage SyncProcessMessage(IMessage msg)
        {
            Preprocess(msg);
            IMessage returnMethod = _next.SyncProcessMessage(msg);
            return returnMethod;
        }

        public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
        {
            throw new InvalidOperationException();
        }

        private void Preprocess(IMessage msg)
        {
            if (!(msg is IMethodMessage)) 
                return;
            IMethodMessage call = msg as IMethodMessage;
            Type type = Type.GetType(call.TypeName);
            string callStr = type.Name + "." + call.MethodName;
            Console.WriteLine("Security validating : {0} for {1}", callStr,
                Environment.UserName);
            // call some security validating code
        }

    }

    public class SecurityProperty : IContextProperty, IContributeObjectSink
    {
        public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
        {
            return new SecurityAspect(next);
        }

        public string Name
        {
            get { return "SecurityProperty"; }
        }
        public void Freeze(Context newContext)
        {
        }
        public bool IsNewContextOK(Context newCtx)
        {
            return true;
        }
    }

    [AttributeUsage(AttributeTargets.All)]
    public class SecurityAttribute : ContextAttribute
    {
        public SecurityAttribute() : base("Security") { }
        public override void GetPropertiesForNewContext(IConstructionCallMessage ccm)
        {
            ccm.ContextProperties.Add(new SecurityProperty());
        }
    }

调用方:

    class Program
    {
        static void Main(string[] args)
        {
            SampleClass s = new SampleClass();
            s.DoSomething();
        }
    }


    [Security]
    [Tracing]
    public class SampleClass: ContextBoundObject
    {
        public void DoSomething()
        {
            Console.WriteLine("do something");
        }
    }

二:Virtual方法及接口的实现

帮助类:

    public class LogHandler : ICallHandler
    {
        /// <summary>
        /// 执行顺序
        /// </summary>
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            Console.WriteLine("方法名: {0}", input.MethodBase.Name);
            Console.WriteLine("参数:");
            for (var i = 0; i < input.Arguments.Count; i++)
            {
                Console.WriteLine("{0}: {1}", input.Arguments.ParameterName(i), input.Arguments[i]);
            }
            Console.WriteLine("方法执行前的处理");
            var retvalue = getNext()(input, getNext);
            Console.WriteLine("方法执行后的处理");
            return retvalue;
        }
    }

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

调用方:

    public interface ISample
    {
        [LogHandler]
        void DoSomething();
        void DoSomethingNoAop();
    }

    class Sample1 : ISample
    {
        public void DoSomething()
        {
            Console.WriteLine("Sample1 do something");
        }

        public void DoSomethingNoAop()
        {
            Console.WriteLine("Sample1 do something no aop");
        }
    }

    public class SampleClass
    {

        [LogHandler]
        public virtual void SampleVirtual()
        {
            Console.WriteLine("Virtual method");
        }

        public void Sample()
        {
            Console.WriteLine("Sampe method");
        }
    }

    class Program {

        static void Main() {
            //针对接口
            var container1 = new UnityContainer()
                .AddNewExtension<Interception>()
                .RegisterType<ISample, Sample1>();
            container1
                .Configure<Interception>()
                .SetInterceptorFor<ISample>(new InterfaceInterceptor());
            container1
                .Configure<Interception>()
                .SetInterceptorFor<SampleClass>(new VirtualMethodInterceptor());
            var sample1 = container1.Resolve<ISample>();
            sample1.DoSomething();
            sample1.DoSomethingNoAop();

            //针对虚拟方法
            var sample2 = container1.Resolve<SampleClass>();
            sample2.SampleVirtual();
            sample2.Sample();

            Console.ReadKey();
        }

    }

可以看到,第二种方法是用Unity实现的,关于Unity,这里多说两句:

Unity的AOP可以从3种标记的情况拦截:
TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject;
VirtualMethod:直接在类的虚方法上进行标记,如上文代码;
InterfaceInterceptor:在接口的方法上进行标记,如上文代码;

代码下载:ConsoleApplication1.rarConsoleApplication2.rar

Creative Commons License本文基于 Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
目录
相关文章
|
2月前
|
XML 数据格式
Karl_Albright:Rougamo、Fody 实现静态Aop
4. Fody 有很多其他的“插件”,大家可以多试试 AutoProperties.Fody: 这个外接程序为您提供了对自动属性的扩展控制,比如直接访问backing字段或拦截getter和setter。 PropertyChanged.Fody: 将属性通知添加到实现INotifyPropertyChanged的所有类。 InlineIL.Fody: 在编译时注入任意IL代码。 MethodDecorator.Fody:通过IL重写编译时间装饰器模式。 NullGuard.Fody: 将空参数检查添加到程序集。
41 4
|
4月前
|
Java 开发者 Spring
面向切面编程(SpringAOP)、通过注解实现AOP代码、AOP的工作流程
面向切面编程(SpringAOP)、通过注解实现AOP代码、AOP的工作流程
55 1
面向切面编程(SpringAOP)、通过注解实现AOP代码、AOP的工作流程
|
4月前
|
JSON 数据安全/隐私保护 数据格式
动态切面
`AdviceConfiguration` 类用于动态注册一个基于 AspectJ 的切面顾问,该顾问通过 `@ConditionalOnExpression` 注解控制是否生效。配置中包含一个从 Apollo 获取的 JSON 值,用于构建方法拦截器的切入点表达式,涉及特定包和类。拦截器 `ControllerAdvice` 实现了 `MethodInterceptor`,用于记录请求日志,包括 URL、参数和执行时间,同时根据配置决定是否对返回结果进行加密。
|
Java Spring
Spring-AOP 切点/切面类型和创建切面
Spring-AOP 切点/切面类型和创建切面
71 0
Spring-AOP 切点/切面类型和创建切面
|
Java Spring
Spring-AOP 动态切面
Spring-AOP 动态切面
147 0
|
前端开发 Java Maven
Spring AOP统一功能处理(切面、切点、连接点、通知)(上)
Spring AOP统一功能处理(切面、切点、连接点、通知)(上)
222 0
|
Java Spring
Spring AOP统一功能处理(切面、切点、连接点、通知)(下)
Spring AOP统一功能处理(切面、切点、连接点、通知)(下)
128 0
|
Java Spring
Spring事务原理一(如何织入AOP)
Spring事务原理一(如何织入AOP)
119 0
|
Java 数据库连接 Spring
JDK动态代理机制(AOP)
这篇文章主要个大家分享JDK动态代理(AOP)
JDK动态代理机制(AOP)
|
XML 移动开发 Java
【框架】[Spring]AOP拦截-使用切点:AspectJExpressionPointcut-切点语言
【框架】[Spring]AOP拦截-使用切点:AspectJExpressionPointcut-切点语言
225 0
【框架】[Spring]AOP拦截-使用切点:AspectJExpressionPointcut-切点语言