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去实现。