(原创) 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去实现。

原文地址:https://www.cnblogs.com/qicosmos/p/3003480.html