zoukankan      html  css  js  c++  java
  • (原创) C++ 轻量级AOP框架

    c++11 boost技术交流群:296561497,欢迎大家来交流技术。

    c++中开源的AOP框架AspectC++需要单独编译才能将切面的代码织入到核心逻辑代码中,感觉使用起来不方便,不能满足快速开发要求。我希望只要实现方法拦截即可,能织入before()和after()操作就行,不追求动态织入。思路是这样的,通过一个包装类,里面定义before()和after()方法,和->运算符重载方法,在重载操作函数中实现before()和after()操作。具体代码如下:

    BaseAspect
     1 #include <boost/shared_ptr.hpp>
     2 
     3 template <typename WrappedType, typename DerivedAspect>
     4 class BaseAspect
     5 {
     6 protected:
     7   WrappedType* m_wrappedPtr; //被织入的对象
     8 
     9   //获取派生的切面对象
    10   DerivedAspect* GetDerived() 
    11   {
    12     return static_cast<DerivedAspect*>(this);
    13   }
    14 
    15   //被织入对象的删除器,用来自动触发切面中的After方法
    16   struct AfterWrapper
    17   {
    18     DerivedAspect* m_derived;
    19     AfterWrapper(DerivedAspect* derived): m_derived(derived) {};
    20     void operator()(WrappedType* p)
    21     {
    22       m_derived->After(p);
    23     }
    24   };
    25 public:
    26   explicit BaseAspect(WrappedType* p) :  m_wrappedPtr(p) {};
    27 
    28 
    29   void Before(WrappedType* p) {
    30      // Default does nothing
    31   };
    32 
    33   void After(WrappedType* p) {
    34      // Default does nothing
    35   }
    36 
    37   //重载指针运算符用来织入切面(Before和After)
    38   boost::shared_ptr<WrappedType> operator->() 
    39   {
    40     GetDerived()->Before(m_wrappedPtr);
    41     return boost::shared_ptr<WrappedType>(m_wrappedPtr, AfterWrapper(GetDerived()));
    42   }
    43 };
    44 
    45 //织入切面的工厂函数, 返回包含被织入对象的切面
    46 template <template <typename> class Aspect, typename WrappedType> 
    47 Aspect<WrappedType> MakeAspect(WrappedType* p) 
    48 {
    49   return Aspect<WrappedType>(p);
    50 }

    BaseAspect为切面的基类,提供了Before()和After()方法,供派生的切面实现;

    下面看看具体的切面实现:一个实现对函数运行时间的统计,一个实现日志功能。

    TimeElapsedAspect
     1 #include <iostream>
     2 #include <boost/chrono/chrono.hpp>
     3 #include <boost/chrono/system_clocks.hpp>
     4 
     5 template<typename WrappedType>
     6 class TimeElapsedAspect : public BaseAspect< WrappedType, TimeElapsedAspect<WrappedType> >
     7 {
     8   typedef  BaseAspect<WrappedType, TimeElapsedAspect<WrappedType> > BaseAspect;
     9   typedef boost::chrono::time_point<boost::chrono::system_clock, boost::chrono::duration<double> > time_point;
    10 
    11   time_point m_tmBegin;
    12 public:
    13   TimeElapsedAspect(WrappedType* p): BaseAspect(p) {}
    14 
    15 
    16   void Before(WrappedType* p) 
    17   {
    18     m_tmBegin = boost::chrono::system_clock::now();
    19   }
    20 
    21   void After(WrappedType* p)
    22   {
    23     time_point end = boost::chrono::system_clock::now();
    24 
    25     std::cout << "Time: " << (end-m_tmBegin).count() << std::endl;
    26   }
    27 };

    TimeElapsedAspect切面实现对函数运行时间统计。

    LoggingAspect
     1 template <typename WrappedType>
     2 class LoggingAspect : public BaseAspect<WrappedType, LoggingAspect<WrappedType> >
     3 {
     4   typedef  BaseAspect<WrappedType, LoggingAspect<WrappedType> > BaseAspect;
     5 public:
     6   LoggingAspect(WrappedType* p): BaseAspect(p) {}
     7 
     8   void Before(WrappedType* p) 
     9   {
    10     std::cout << "entering" << std::endl;
    11   }
    12 
    13   void After(WrappedType* p) 
    14   {
    15     std::cout << "exiting" << std::endl;
    16   }
    17 
    18 };

    LoggingAspect实现日志记录

    现在来看看测试代码

    TestAop
    class IX
    {
    public:
        IX(){}
        virtual ~IX(){}
    
        virtual void g()=0;
    private:
    
    };
    
    class X : public IX
    {
    public:
      void g() 
      {
        std::cout << "it is a test" << std::endl;
      }
    
    };
    
    void TestAop()
    {
        boost::shared_ptr<IX> p(new X());
        MakeAspect<TimeElapsedAspect>(p.get())->g();
        MakeAspect<LoggingAspect>(p.get())->g();
    }

     测试结果:

    总结:

    这个简单的AOP实现,可以实现对类的方法进行拦截,具体切面自由定制,不过还有个地方不太完善,还不支持切面的组合,这个可以用TypeList去实现。

  • 相关阅读:
    七、Struts2之文件上传与下载
    八、Struts2之OGNL
    五、Struts2之类型转换
    wpf坐标转换相关
    wpf拖拽封装类
    获取Bitmap的Graphics
    Win32定时器
    vs2010调试dll
    使用GDI+ 保存HDC为位图文件
    在c++中使用.net
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3003480.html
Copyright © 2011-2022 走看看